HDU3433 【时间的二分+DP最优解】
题意:
有n个人,X个任务A,Y个任务B,
给出每个人做A做B的时间,一个人只能在某个时刻做一个工作,
有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\n",cas++,left); } return 0; }