DP大乱炖 A

There are two kinds of tasks, namely A and B. There are N workers and the i-th worker would like to finish one task A in ai minutes, one task B in bi minutes. Now you have X task A and Y task B, you want to assign each worker some tasks and finish all the tasks as soon as possible. You should note that the workers are working simultaneously.

input:In the first line there is an integer T(T<=50), indicates the number of test cases. 
In each case, the first line contains three integers N(1<=N<=50), X,Y(1<=X,Y<=200). Then there are N lines, each line contain two integers ai, bi (1<=ai, bi <=1000). 

output:For each test case, output “Case d: “ at first line where d is the case number counted from one, then output the shortest time to finish all the tasks.

 Sample input:

3
2 2 2
1 10
10 1
2 2 2
1 1
10 10

3 3 3
2 7
5 5
7 2

 Sample output:

 

Case 1: 2
Case 2: 4
Case 3: 6
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3433
题目分析:
你要明白最多所需花费时间为所有人中花费时间最多的人的时间,对于这个时间,我们可以二分得到,然后用DP来验证。
详细DP验证过程,请看代码注释
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iomanip>
#include<algorithm>
using namespace std;
int t;
int n,m,f[55][510],a[51],b[51],x,y,l,r;
bool work(int p)
{
    memset(f,-1,sizeof(f));
    //每次验证之前需要把数组全部赋值为负 
    f[0][0]=0;
    for(int i=1;i<=n;i++)//枚举每一个工人 
    {
        for(int j=0;j<=x;j++)//在此处,我们做一个类似于背包问题的dp,把所需要做A时间看为背包代价 
        {
            f[i][j]=f[i-1][j];
            for(int k=0;k<=j;k++)//在做j个A事件时能做的最多的B事件 
            {
                if(p-k*a[i]<0) break;
                if(f[i-1][j-k]!=-1)
                f[i][j]=max(f[i][j],f[i-1][j-k]+(p-k*a[i])/b[i]);
            }
        }
    }
    if(f[n][x]>=y) return true;//如果在做完所有A事件的时候所能做最多数量的B事件。 
    else return false;
}
int main()
{
    scanf("%d",&t);
    for(int qw=1;qw<=t;qw++)
    {
        scanf("%d%d%d",&n,&x,&y);
        for(int i=1;i<=n;i++){scanf("%d%d",&a[i],&b[i]);}
        l=1,r=1000000;
        while(l+1<r)//二分枚举最短时间 
        {
            int mid=(l+r)/2;
            if(work(mid))r=mid;
            else l=mid;
        }
        cout<<"Case "<<qw<<": ";
        if(work(l))cout<<l<<endl;
        else cout<<r<<endl;
    }
    return 0;
} 
View Code

 

posted @ 2017-08-14 16:03  mybing  阅读(144)  评论(0编辑  收藏  举报