标签:
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 1112 | Accepted: 482 |
Description
Input
Output
Sample Input
1 3 20 1 1 2 4 1 6
Sample Output
18
1 /*既然动态规划方程中要转移的量太多,那么我们就把时间作为二分的对象,对时间进行二分,假设一个最短时间(每个人都不能超过的时间),进行DP,f[i][j]表示是前i个人做j个A项目所能做的最多的B项目的数目, 2 方程:d[i][j] = max { d[i][j] , d[i][j - k] + (time - A[i] * k) / B[i] } 3 枚举第i个人做k个A项目,剩下的时间用来做B项目,只要检查d[i][m]》=m就是能够到这个时间。 4 当然我们也可以用滚动数组压缩空间。*/ 5 #define N 101 6 #include<iostream> 7 using namespace std; 8 #include<cstdio> 9 #include<cstring> 10 struct QU{ 11 int n,m,A[N],B[N],f[N]; 12 void init(int x,int y) 13 { 14 n=x;m=y; 15 memset(A,0,sizeof(A)); 16 memset(B,0,sizeof(B)); 17 memset(f,0,sizeof(f)); 18 } 19 void add(int a,int b,int i) 20 { 21 A[i]=a;B[i]=b; 22 } 23 bool check(int V) 24 { 25 memset(f,-1,sizeof(f)); 26 for(int i=0;i<=m;++i) 27 {/*初始化第一个人的做i个A项目的情况*/ 28 if(i*A[1]>V) break; 29 f[i]=max(f[i],(V-i*A[1])/B[1]); 30 } 31 if(f[m]>=m) return true; 32 for(int i=2;i<=n;++i) 33 { 34 for(int j=m;j>=0;--j) 35 {/*枚举前i-1人做了多少个A*/ 36 for(int k=0;k<=j;++k) 37 {/*枚举第i个人做了k个A项目*/ 38 if(V<k*A[i]) break; 39 if(f[j-k]!=-1) 40 f[j]=max(f[j],f[j-k]+(V-k*A[i])/B[i]); 41 /*注意前-1个人可能做不到j-k个项目,这时候如果转移,那就是前i-1个人总共花了-1时间,显然不合题意*/ 42 } 43 } 44 if(f[m]>=m) return true; 45 } 46 return false; 47 } 48 }Q; 49 int main() 50 { 51 int tes; 52 scanf("%d",&tes); 53 int n,m; 54 while(tes--) 55 { 56 scanf("%d%d",&n,&m); 57 Q.init(n,m); 58 int a,b; 59 int maxx=-1; 60 for(int i=1;i<=n;++i) 61 { 62 scanf("%d%d",&a,&b); 63 Q.add(a,b,i); 64 maxx=max(maxx,max(a,b)); 65 } 66 int l=0,r=maxx*m*2; 67 int mid; 68 while(l<=r) 69 { 70 mid=(l+r)>>1; 71 if(Q.check(mid)) 72 r=mid-1; 73 else l=mid+1; 74 } 75 printf("%d\n",l); 76 77 } 78 return 0; 79 }
二分+动态规划 POJ 1973 Software Company
标签:
原文地址:http://www.cnblogs.com/c1299401227/p/5572158.html