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

【题目链接】
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 long
const 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值