HDU3535 AreYouBusy

 1 #include<iostream>
 2 using namespace std;
 3 int Max(int a,int b,int c){
 4     if(a<b) a=b;
 5     if(a<c) a=c;
 6     return a; 
 7 }
 8 int f[105][105];
 9 int main()
10 {
11     int n,T,i,j,k,m,s,c,g;
12     while(~scanf("%d%d",&n,&T)){
13         memset(f,0,sizeof(f));
14         for(i=1;i<=n;i++){
15             scanf("%d%d",&m,&s);
16             for(j=0;j<=T;j++)
17                 f[i][j]=s?f[i-1][j]:INT_MIN;  //如果 s==0 需赋值为无穷小,
18                 //这样才能保证至少使用一次 ,因为一件也不使用对应结果就为负无穷,
19                 // s!=0时,要先传递f[i-1][j]的值给f[i][j] 
20             for(j=1;j<=m;j++){
21                 scanf("%d%d",&c,&g);
22                 for(k=T;k>=c;k--){ //递推顺序不能颠倒,因为每种工作只能被完成一次
23                                 //如 01背包中的滚动数组 
24                     if(s==1) f[i][k]=max(f[i][k],f[i-1][k-c]+g);  //01背包模型最多能选取一件 
25                     else f[i][k]=Max(f[i][k],f[i-1][k-c]+g,f[i][k-c]+g); //可以选取多件,
26                     //所以在 max中多加了了一个 f[i][k-c]+g 以致可以选取多个 
27                 }
28             }
29         }
30         printf("%d\n",max(f[n][T],-1)); //假如不存在解,f[n][T]则为负无穷 
31     }
32     return 0;
33 } 

一种混合+组合背包问题!很经典

原文地址:https://www.cnblogs.com/shihuajie/p/3047905.html