HDU 1039 修路

Description

前段时间,某省发生干旱,B山区的居民缺乏生活用水,现在需要从A城市修一条通往B山区的路。假设有A城市通往B山区的路由m条连续的路段组成,现在将这m条路段承包给n个工程队(m≤ 300)。为了修路的便利,每个工程队只能分配到连续的若干条路段(当然也可能只分配到一条路段或未分配到路段)。假设每个工程队修路的效率一样,即每修长度为1的路段所需的时间为1。现在给出路段的数量m,工程队的数量n,以及m条路段的长度(这m条路段的长度是按照从A城市往B山区的方向依次给出,每条路段的长度均小于1000),需要你计算出修完整条路所需的最短的时间(即耗时最长的工程队所用的时间)。

Input

第一行是测试样例的个数,接下来是T个测试样例,每个测试样例占2行,第一行是路段的数量m和工程队的数量n,第二行是m条路段的长度。

Output

对于每个测试样例,输出修完整条路所需的最短的时间。

Sample Input

2

4 3

100 200 300 400

9 4

250 100 150 400 550 200 50 700 300

Sample Output

400

900

解题思路

用opt[k][j-1]表示前k条路段由前j-1个工程队修完的最早的时间,用sum[i]表示前i条路段只由1个工程对完成的所需的时间,则sum[i]-sum[k]表示从第K+1条路段到第i条路段由1个工程队完成所需的时间。 

状态转移方程:

 opt[i][j] = max(opt[k][j-1], sum[i]-sum[k]);

 即前i条路段由前j个工程队修完的最早的时间为前k条路段由前j-1个工程队修完的最早的时间和从第K+1条路段到第i条路段由1个工程队完成所需的时间这两者中大的一个。 

 

code:

#include<stdio.h>
#include<stdlib.h>
#define INF 0x3f3f3f3f
int max(int x,int y)
{
    if(x>y)
        return x;
    return y;
}
int main()
{
    int a[302];
    int opt[302][302];
    int sum[302];
    int t,n,m,i,j,tot,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&m,&n);
        for(i=1;i<=m;i++)
            scanf("%d",&a[i]);
        sum[0]=0;
        for(i=1;i<=m;i++)
            sum[i]=sum[i-1]+a[i];
        opt[1][1]=sum[1]-sum[0];
        opt[2][1]=sum[2]-sum[0];
        opt[2][2]=max(opt[1][1],sum[2]-sum[1]);
        for(i=3;i<=m;i++)
        {
            opt[i][1]=sum[i]-sum[0];
            for(j=2;j<=i;j++)
            {
                tot=INF;
                for(k=j-1;k<=i-1;k++)
                    if(max(opt[k][j-1],sum[i]-sum[k])<tot)
                        tot=max(opt[k][j-1],sum[i]-sum[k]);
                opt[i][j]=tot;
            }
        }
        printf("%d\n",opt[m][n]);
    }
    return 0;
}
posted @ 2012-03-14 17:48  'wind  阅读(434)  评论(0编辑  收藏  举报