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