HDU3433 【时间的二分+DP最优解】

题意:
有n个人,X个任务A,Y个任务B,
给出每个人做A做B的时间,一个人只能在某个时刻做一个工作,

问最短时间完成所有工作。

思路:

二分n个人用的时间,判断最优条件用DP。

可以二分就是因为时间越多的话肯定能做更多的task啊。

真的好神奇!n个人可以同一时间一起做事,那么对于给定的时间,也就是说每个人都拥有这么多时间,无非就是他会去怎么安排,那么就DP啊。

dp[i][j] 代表前 i 个人搞了 j 个A以后,还能搞多少个B;

判断一发就是个0/1背包,背包容量就是时间,枚举第i个人做A任务的数量 j ,那么B的数量 (time-a[i]*(j-k))/b[i];

//话说 对于求时间的问题,用二分搞的好多了!!!以后要想过去!!!DP最优解。

//突然发现对于二分这个搞法,真是每次想到都追悔莫及,瞎歪歪了一个点子:

//钱越多东西就可以买的越多;时间花的越多,事情就可以办的更多;the more...,the more...就可以用二分

#include<bits/stdc++.h>
using namespace std;
typedef __int64 LL;
int dp[210];
int a[60];
int b[60];
int n,X,Y;

bool DP(int time)
{
    memset(dp,-1,sizeof(dp));
    dp[0]=0;

    for(int i=1;i<=n;i++)
    {
        for(int j=X;j>=0;j--)//枚举能够处理j个A
        {
            for(int k=j;k>=0;k--)
            {
                if(time>=(j-k)*a[i]&&dp[k]!=-1)
                    dp[j]=max(dp[j],dp[k]+(time-a[i]*(j-k))/b[i]);
            }
        }
        if(dp[X]>=Y)
            return true;
    }
    return false;
}
int main()
{
    int T,cas=1;
    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 left=0;
        int right=600*1000;
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(DP(mid))
                right=mid;
            else
                left=mid+1;
        }
        printf("Case %d: %d
",cas++,left);
    }
    return 0;
}



原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777479.html