【题解】hdu3535 混合背包

题目链接
思路摘抄自大佬博客
首先如果存在最优解, 我们可以互换不同工作集合的处理顺序, 依然能得到最优解. 那么我们下面只需要处理每个单独的工作集合即可.
令dp[i][j]==x表示处理完前i组工作集,所花时间<=j时的快乐值为x。每得到一组工作就进行一次DP,所以dp[i]为第i组的结果。下面对三种情况进行讨论。
1.该集合内至少要选1件工作时. 要保证至少选1个第i类工作, 可以从第i-1类的结果dp[i-1]来更新dp[i].也可以用 01背包的思想, 从本类的前一个工作更新后一个工作.
初始化:dp[i]全为负无穷.(即-INF)
状态转移方程为:
dp[i][k]=max{dp[i][k],dp[i-1][k-cost[j]]+val[k],dp[i][k-cost[j]]+val[j] }
2.该集合内最多选1件工作时. 只能从上一层的结果dp[i-1]来更新dp[i]了.(想想为什么)
初始化:dp[i]==dp[i-1].状态转移方程为dp[i][k]=max{dp[i][k],dp[i-1][k-cost[j]]+val[k]}.
3. 该集合内工作可以随便选. 这就是1个普通的01背包问题了.
初始化:dp[i]==dp[i-1].
状态转移方程为:
dp[i][k]=max{dp[i][k],dp[i-1][k-cost[j]]+val[k],dp[i][k-cost[j]]+val[j] }
最终所求:dp[n][t]的值

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
int n;//n组工作 
int t;//t分钟 
int dp[110][110];//处理前i组工作,所花时间<=j的幸福点 
int cost[110];//成本 
int val[110];//幸福点 
int main()
{
    //freopen("in.txt","r",stdin);
    int i,j,k;
    while(scanf("%d%d",&n,&t)==2)
    {
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
        {
            int m,s;
            scanf("%d%d",&m,&s);//m个作业,类型s 
            for(k=1;k<=m;k++)
            scanf("%d%d",&cost[k],&val[k]);
            if(s==0)//至少选一个的01背包问题 
            {
                for(j=0;j<=t;j++)dp[i][j]=-INF;//初始化
                for(k=1;k<=m;k++)
                for(j=t;j>=cost[k];j--)
                {
                    dp[i][j]=max(dp[i][j],dp[i][j-cost[k]]+val[k]);
                    dp[i][j]=max(dp[i][j],dp[i-1][j-cost[k]]+val[k]);
                    //交换顺序会错 
                } 
            }
            else if(s==1)//至多选1个的01背包问题 
            {
                for(j=0;j<=t;j++)dp[i][j]=dp[i-1][j];
                for(k=1;k<=m;k++)
                for(j=t;j>=cost[k];j--)//无所谓顺序 
                {
                    dp[i][j]=max(dp[i][j],dp[i-1][j-cost[k]]+val[k]);
                }
            }
            else if(s==2)//随便选的01背包 
            {
                for(j=0;j<=t;j++)dp[i][j]=dp[i-1][j];
                for(k=1;k<=m;k++)
                for(j=t;j>=cost[k];j--)//只能逆序
                dp[i][j]=max(dp[i][j],dp[i][j-cost[k]]+val[k]); 
            }
        }
        int ans=max(dp[n][t],-1);
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41958841/article/details/81636251
今日推荐