题目:http://acm.hdu.edu.cn/showproblem.php?pid=3535
题意:
有n个组的工作,有t的时间去做
对于组有三种类型
0至少选一个
1最多选一个
2随意,拿或者不拿,选其中多少都可以
每组每件事有花费的时间和收益
取尽量高的收益
思路:
三种情况:
0:至少选一个:dp[i][k] 初始化为负无穷,所以跟上一组的比dp[i-1][k-cost[j]]+val[j]肯定比dp[i][k]大,肯定能选一个,还能选这组的前一个dp[i][k-cost[j]]+val[j]。即可以通过上一组和该组前几个比较出最大的。
1:最多选一个,把上租的赋给这组就行,max(dp[i][k],dp[i-1][k-cost[j]]+val[j])
2:随意选几个都行。把上租的赋给这组,max(dp[i][k],dp[i][k-cost[j]]+val[j],dp[i-1][k-cost[j]]+val[j])
由于0类的存在,可能达不到要求,即比-1小的情况输出-1。
然而体积为0是比较操蛋的,max(dp[i-1][k]+val,dp[i][k]),此时选了体积为0的物品,
下次比较max(dp[i][k]+val,dp[i][k]),又加了一次,自己更新自己,所以直接先更新自己(反正从负无穷开始加,下次肯定比掉自己)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=100+5;
#define INF 1e8
int n;
int t;
int dp[maxn][maxn];
int cost[maxn];
int val[maxn];
int main(){
while(cin>>n>>t){
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
int m,s;
cin>>m>>s;
for(int j=1;j<=m;j++)
cin>>cost[j]>>val[j];
if(s==0){
for(int j=0;j<=t;j++) //肯定改到t啊
dp[i][j]=-INF;
for(int j=1;j<=m;j++){
for(int k=t;k>=cost[j];k--){
dp[i][k]=max(dp[i][k-cost[j]]+val[j],dp[i][k]);
dp[i][k]=max(dp[i-1][k-cost[j]]+val[j],dp[i][k]);
}
}
}
else if(s==1){
for(int j=0;j<=t;j++)
dp[i][j]=dp[i-1][j];
for(int j=1;j<=m;j++)
for(int k=t;k>=cost[j];k--)
dp[i][k]=max(dp[i][k],dp[i-1][k-cost[j]]+val[j]);
}
else if(s==2){
for(int j=0;j<=t;j++)
dp[i][j]=dp[i-1][j];
for(int j=1;j<=m;j++)
for(int k=t;k>=cost[j];k--){
dp[i][k]=max(dp[i][k-cost[j]]+val[j],dp[i][k]);
dp[i][k]=max(dp[i-1][k-cost[j]]+val[j],dp[i][k]);
}
}
}
int ans=max(dp[n][t],-1);
cout<<ans<<endl;
}
return 0;
}