描述 Description
假設有n 個任務由k 個可並行工作的機器完成。完成任務i 需要的時間為ti。試設計一個算法找出完成這n 個任務的最佳調度,使得完成全部任務的時間最早。
一旦任務i由某台機器完成,中途不能更換機器。
編程任務:
對任意給定的整數n 和k,以及完成任務i 需要的時間為ti,i=1~n 。編程計算完成這n個任務的最佳調度
輸入格式 Input Format
第一行有2 個正整數n 和k。
第2 行的n 個正整數是完成n 個任務需要的時間。
輸出格式 Output Format
完成全部任務的最早時間。
樣例輸入 Sample Input
7 3
2 14 4 16 6 5 3
樣例輸出 Sample Output
17
這道題我最開始寫的時候可以說是zz了,怎么說,最開始連題都沒讀懂,甚至看不出這是道回溯題(我真是太弱啦!!),當時感覺和接水問題差不多(好像確實差不多?不是我的鍋),在lyz大佬的指點下,才算是大概有些頭緒。然后敲了沒幾行又卡了,最后不得已搜了兩篇題解,算是徹底明白這題怎么寫了。
換一個角度思考一下,一個k個可並行的機器,實際就相當於把這k個機器當做容器,將時間填入容器中去,按照時間來搜索,然后一層一層搜索,每次傳的是容器中時間的最大值(在這個時間內我們可以不斷地用其他機器完成別的工作,而當累加時間大於最大時間是,我們就不得已擴充容器了)
//剪枝可以使這個程序快到飛起,否則就等着tle吧….
代碼如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,k; 4 int a[100086],s[100086]; 5 int minn=1000000; 6 bool ltt(int x,int y){ 7 return x>y;} 8 inline void dfs(int b,int c){ 9 if(c>=minn) return;//剪枝1號 10 if(b>n){ 11 if(c<minn) 12 minn=c; 13 return; 14 } 15 for(int i=1;i<=k;i++){ 16 if(s[i]+a[b]<=minn){//剪枝2號 17 s[i]+=a[b]; 18 dfs(b+1,max(c,s[i])); 19 s[i]-=a[b]; 20 } 21 } 22 return; 23 } 24 int main() { 25 cin>>n>>k; 26 memset(s,0,sizeof(s)); 27 for(int i=1;i<=n;i++) 28 cin>>a[i]; 29 sort(a+1,a+n+1,ltt);//從大到小排序可以更快接近最優解 30 dfs(1,0); 31 cout<<minn<<endl; 32 return 0; 33 }
