http://acm.hdu.edu.cn/showproblem.php?pid=3535
(1)本题是三种背包的综合应用, 至少选一种、最多选一种、任意选;
(2)边读入边处理,可以节省一定的空间,也是代码更加清晰(如 m 就不用开数组m[120]);
(3)初始化细节:
1)for(j=0;j<=t;j++) dp[i][j]=-(1<<28);
2)for(j=0;j<=t;j++) dp[i][j]=dp[i-1][j];
3)for(j=0;j<=t;j++) dp[i][j]=dp[i-1][j];
写题时, 我用了for(j=0;j<=t;j++) dp[i][j]=0; 检查了好一会儿。
具体代码:
View Code
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int n, t; int m, s; int c[120], g[120]; int dp[120][120]; int main() { int i, j, k; while(scanf("%d%d", &n, &t)!=EOF) { memset(dp, 0, sizeof(dp)); for(i=1;i<=n;i++) { scanf("%d%d", &m, &s); for(j=1;j<=m;j++) { scanf("%d%d", &c[j], &g[j]); } if(s==0) //at least 1 { for(j=0;j<=t;j++) dp[i][j]=-(1<<28); for(j=1;j<=m;j++) { for(k=t;k>=c[j];k--) dp[i][k]=max(dp[i][k], dp[i][k-c[j]]+g[j]), dp[i][k]=max(dp[i][k], dp[i-1][k-c[j]]+g[j]); } } else if(s==1) //at most 1 { for(j=0;j<=t;j++) dp[i][j]=dp[i-1][j]; for(j=1;j<=m;j++) for(k=t;k>=c[j];k--) dp[i][k]=max(dp[i][k], dp[i-1][k-c[j]]+g[j]); } else if(s==2) //free { for(j=0;j<=t;j++) dp[i][j]=dp[i-1][j]; for(j=1;j<=m;j++) for(k=t;k>=c[j];k--) dp[i][k]=max(dp[i][k], dp[i][k-c[j]]+g[j]); } } if(dp[n][t]<0) printf("-1\n"); else printf("%d\n", dp[n][t]); } return 0; }
