平衡負載(2013年百度之星3月23號競賽題目一)


平衡負載

  Du熊正在負責一個大型的項目,目前有K台服務器,有N個任務需要用這K台服務器來完成,所以要把這些任務分成K個部分來完成,在同上台服務器上執行的任務必須是連續的任務,每個任務有各自需要的執行時間。

  例如N=5,K=2,每個任務需要時間分別為5,3,1,4,7分鍾,那么我們可以分成(5)(3 1 4 7)兩部分,這樣第一台服務器所花時間就是5分鍾,而第二台機器需要花15分鍾,當然,所有任務完成的時間是按最遲完成的那台服務器的時間,即這樣划分的話完成所有任務所需要的時間就是15分鍾。而另外一種划分方法是(5 3 1)(4 7),這種划分方案完成所有任務的時間就是11分鍾,也是最優的一種划分方案。

  現在你的任務就是根據給定的N,K和每個任務要花費的時間,找出使完成所有任務時間最短的方案。

  輸入:

    多組輸入。

    第一行輸入N和K(1<=K<=N<=10000)。

    第二行輸入N個不大於1000的正整數,表示各個任要花費的時間。

    N=K=0表示輸入結束。

  輸出:

    每行輸出一個整數,對應對於每個數據(除了N=K=0不用輸出)。

  樣例輸入:

    5 1
    5 3 1 4 7
    5 2
    5 3 1 4 7
    5 3
    5 3 1 4 7
    10 3
    1 2 3 4 5 6 7 8 9 10
    0 0

  樣例輸出:

    20
    11
    8
    21
 
思路:
  初看這個題目,覺得可以用dfs來做,不過效率肯定是比較低的,所以后來想想,其實這道題目挺符合dp使用條件的,有這重復的子問題,有這最優子結構和無后效性,所以就打算用dp做了,首先定義狀態dp[x][y],表示將前y個任務分到前x台服務器,完成前y個任務的最短時間。狀態轉移方程為:
  dp[x][y] = min{max{dp[x - 1][y1] , sy}} 其中y1取值為[x - 1, y - 1],sy = time[y1 + 1] + time[y2 + 1] + ...+time[y]
  如果直接定義dp[10000][10000],那空間太大了,通過狀態轉移方程可以知道,dp[x][y]只與dp[x - 1][y1]有關,所以可以定義dp[2][10000]來節省空間。代碼如下:
 1 #include <stdio.h>
 2 
 3 #define max(a, b) a > b ? a : b
 4 int n, k;
 5 int time[10005];
 6 int dp[2][10005];
 7 int temp[10005];
 8 
 9 int main(void)
10 {
11     int i, j, min, l;
12 
13     while (scanf("%d%d", &n, &k), n && k)
14     {
15         for (i = 1; i <= n; i ++)
16             scanf("%d", &time[i]);
17         dp[1][1] = time[1];
18         for (i = 2; i <= n; i ++)
19             dp[1][i] = dp[1][i - 1] + time[i];
20         for (j = 2;  j <= k; j ++)
21         {
22             for (i = j; i <= n; i ++)
23             {
24                 min = 100000000;
25                 temp[0] = 0;
26                 for (l = i - 1; l >= j - 1; l --)
27                 {
28                     temp[i - l] = temp[i - l - 1] + time[l + 1];
29                     if (max(dp[(j + 1) % 2][l] , temp[i - l]) < min)
30                         min = max(dp[(j + 1) % 2][l] , temp[i - l]);    
31                 }
32                 dp[j % 2][i] = min;
33                 printf("%d ", dp[j % 2][i]);
34             }
35             printf("\n");
36         }
37         printf("%d\n", dp[k % 2][n]);
38     }
39     return 0;
40 }
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM