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;
}