平衡负载(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 }
 
 
posted @ 2013-04-16 09:13  在于思考  阅读(1476)  评论(6编辑  收藏  举报