HDU3433 A Task Process(dp+二分查找)

来源:互联网 发布:诸葛亮知天下事 编辑:程序博客网 时间:2024/05/31 19:50

【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=3433

题目意思

有n个人,和a,b两种任务,现在给你要n个人完成的a,b任务的总个数,和每个人完成a,b任务的时间,每个人完成任务互不影响,问最短达标时间。

解题思路

题目给了人数,a,b任务,求时间。首先由于求输出的时间为最优的,所以分配给每个人时间相同,接着又因为知道一个人a任务完成个数根据时间就能求出完成b的任务数,这样理论上开个三维的dp数组(人数,任务数,时间。。。值为b任务数判断b是否达标,下同)就可以找出最优解,但是时间值非常大,所以用二分来求二维dp数组(人数,a任务数)最优解。

代码部分

#include <bits/stdc++.h>using namespace std;#define LL long longconst int maxn=205;const int INF=0x3f3f3f;int dp[maxn][maxn];   ///存第i个人完成j个a任务还能完成多少个b任务int a[maxn],b[maxn];int n,x,y;bool DP(int t){    memset(dp,-1,sizeof(dp));    dp[0][0]=0;    for (int i=1;i<=n;i++)    {        if (dp[i][x]>=y)  ///如果前i个人在完成x个a任务后还能完成大于y个b任务就返回真            return true;        for (int j=0;j<=x;j++)  ///前i-1个人完成a任务数        {            if (dp[i-1][j]!=-1)  ///如果前i-1个人能完成j个任务            {                for (int k=0;k<=min(t/a[i],x-j);k++)///枚举完成k个a任务后还能完成多少个b任务                {                    int add=(t-a[i]*k)/b[i];   ///完成的b任务数                    dp[i][j+k]=max(dp[i-1][j]+add,dp[i][j+k]);                 }            }        }    }    if (dp[n][x]>=y)        return true;    else return false;}int main(){    int cas=1,t,ans=0;    scanf("%d",&t);    while(t--)    {        scanf("%d %d %d",&n,&x,&y);        for (int i=1;i<=n;i++)        {            scanf("%d %d",&a[i],&b[i]);        }        int l=0,r=INF;        printf("Case %d: ",cas++);        while (l<=r)  ///二分时间找最优解        {            int mid=(l+r)>>1;            if (DP(mid))            {                ans=mid;                r=mid-1;            }            else            l=mid+1;        }        printf("%d\n",ans);    }    return 0;}