序列劃分(正)
阿新 • • 發佈:2018-12-09
題目
總工程師 題目描述 有M個軟體工程師正在完成一個大型軟體,需要開發若干個元件。 已知完成每個元件的開發時間儲存在一個數組A裡面,每個工程師只能獨立完成連續的元件, 並且所有的工程師都是並行工作, 請輸出完成這個軟體需要的最少時間
輸入說明 程式從當前路徑下的data.txt檔案中讀取測試資料。 第一行會有1個數值,表示M 第二行則是A陣列,元素之間以空格隔開
輸出說明 向標準輸出列印完成軟體需要的最少時間
示例 輸入:
2 3 1 4 表示有兩個工程師來完成3 個元件。 3個元件耗時分別是3/1/4.
輸出:
4 最好的分配方式為第一個工程師完成元件 1,2, 所以需要時間為4; 第二個工程師完成3, 所需要時間為4, 因為並行工作, 所以最小時間是4.
思路
- 注意每個工程師只能獨立完成連續的元件,故該題實際就是對序列進行劃分,設劃分M個序列後的最大子序列和為value,則題目需要找到一個最小的value。
- 而且時間肯定是正的,那麼不需要考慮負數序列。
- 那麼可以用貪心去解決了:假設正確答案是V,我們就假設一個值value去逼近V,直到用value可以劃分M個序列,而value-1不能劃分M個序列,此時value值即為V。
程式碼
#include <iostream>
#include <fstream>
using namespace std;
int m, n, a[1024];
bool judge(int value) {
int sum = 0, cnt = 0;
for (int i = 0; i<n; i++) {
// 若預分配超過value
if (sum + a[i] > value) {
sum = a[i];
cnt++;
// 劃分超過m
if (cnt == m)
return false;
}
else {
sum += a[i];
}
}
return true;
}
int main() {
int sum = 0;
fstream file("data.txt");
file >> m;
while (!file.eof()) {
file >> a[n];
sum += a[n++];
}
while (sum) {
if (judge(sum) && !judge(sum - 1))
break;
sum--;
}
cout << sum << endl;
system("pause");
return 0;
}
//問題分析:
//能否使m個連續子序列所有的s(i)均不超過x,則該命題成立的最小的x即為答案。該命題不難判斷,只需貪心,每次儘量從左
//向右儘量多劃分元素即可。
//我們把該問題轉化為遞迴分治問題,類似於二分查詢。首先取Sum和元素最大值的中值x,如果命題為假,那麼答案比x大;
//如果命題為真,則答案小於等於x。問題得解,複雜度為O(n*logSum)
#include<stdio.h>
int num[1005], n, m,Max=0,Left=0,Right=0;
/* 判斷劃分所子序列其和是否都不大於x 是-1,否-0*/
int Judge(int SumMin)
{
//每次往右劃分,劃分完後,所用的劃分線不大於m-1個即可
int count = 0, LeftSum = 0;//count已劃分子序列個數(其實count的值為劃分斜槓個數),LeftSum即將劃分的序列從右開始累和
for (int i = 0; i<n; i++)
{
if (num[i]>SumMin)
return 0;//如果序列中有元素的值大於SumMin,則無論怎麼劃分都不成立
if (LeftSum + num[i]>SumMin)
{
count++;
LeftSum = num[i];
if (count>m - 1)
return 0;//已劃分的子序列個數超過m
}
else
LeftSum += num[i];
}
return 1;
}
int BinarySelect()
{
while (Left<Right)
{
int mod = Left + (Right - Left) / 2;
if (Judge(mod))
Right = mod;
else
Left = mod + 1;
}
return Left;
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++)
{
scanf("%d", &num[i]);
if (num[i] > Left)
Left = num[i];
Right += num[i];
}
printf("%d\n",BinarySelect());
return 0;
}