百度之星--平衡负载(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

 

解答思路:最优划分用动态规划解决,我认为其中比较关键的是

1)如何转化问题,即使用符号表示待解决的问题。

本题中,设f(i,k)表示数组a[i…N]分成k部分的最优值。

2)状态转移方程。

本题为f(i,k)=min(j)max{f(j,k-1), sum(i, j-1)}, i < j <= N-k+2   ,k = 2,…,K.

3)初始状态的确定。

本题为f(i,1) = sum(i, N), i = 1,...,N.即k=1为初始状态。

Ps:我觉得做动态规划的时候,最好还是找一个小规模问题,列一个表计算一下,就能把握i,j,k的范围和加深对题目解答的理解,切记切记!

 

#include <stdio.h>
#define MIN(a,b) (a)<(b)?(a):(b)
#define MAX(a,b) (a)>(b)?(a):(b)

int a[1001];
int f[1001][1001];
int tmpMax[1001];

int sum(int i, int j)
{
    int s = 0;
    for (int k = i; k <= j; k++)
    {
        s+= a[k];
    }
    return s;
}

int main()
{
    int N, k;
    scanf("%d %d",&N,&k);
    do 
    {
        int i = 1;;
        while (i<=N)
        {
            scanf("%d", &a[i]);
            i++;
        }
        //f[i][k]表示a[i...N] 分成k 部分的最优划分方案
        for (int i = 1; i <= N; i ++)
        {
            f[i][1] = sum(i,N);
        }
        //DP
        int tmpmin;
        for (int nk = 2; nk <= k; ++nk)
        {
            for (int i = 1; i < N - nk + 2; i++)
            {
                tmpmin = 0x7FFFFFFF;
                for (int j = i+1; j <= N - nk + 2; j++)
                {
                    //对每个j,比较f[j][nk-1] 和sum(i,j-1)两部分的最大值
                    tmpMax[j] = -1;
                    tmpMax[j] = MAX(f[j][nk-1], sum(i,j-1));
                    //对所有的j的最大值,取最小值即为f[i][nk]
                    tmpmin= MIN(tmpmin,tmpMax[j]);
                }
                f[i][nk] = tmpmin;            
            }

        }
        printf("%d\n",f[1][k]);

        scanf("%d %d",&N,&k);
    } while (N != 0 && k != 0);
}

 

posted @ 2013-03-27 23:00  hust_枫  阅读(380)  评论(0编辑  收藏  举报