Test 6.29 T1 预算方案

问题描述

“我需要你为我制订一个购物的方案。我将要为我的宫殿增置一些家具。有n 种备选家具,家具有主件和附件之分。在购买某个主件的附件之前,我必须先购买其对应的主件。某一主件的附件不会是另一样家具所对应的主件。每一件家具 i 都有自己的价格 x 与重要度 y。要完成这个问题,你需要在 1s 内得出我在花费不超过 m 元的情况下所能得到的家具的价格与重要度乘积的和最大。”CJK 不敢怠慢,立刻开始码代码。

输入格式

第一行两个数,m 和 n,接下来 n 行,第 i 行三个数 x,y,z,分别表示该物品的价格、重要度及它的主件的编号(z 为 0 表示该物品为主件)。

输出格式

每一样购买的家具的价格与重要度的乘积的和。(形如 xiyi+xjyj+......,i、j 为购买的家具的编号)

样例输入输出

样例输入1

1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

样例输出1

2200

样例输入2

1000 5
800 2 0
400 5 1
300 5 1
400 3 1
500 2 1

样例输出2

1600

解析

如果不考虑主附件,这就是一个裸的完全背包问题。但是如果选附件就必须选主件,所以我们考虑如何处理依赖关系。我们可以设一个分数组表示选了当前主件后用这个主件的附件跑01背包后的结果。每次DP前,都把之前主数组的结果复制到分数组中,跑完背包后再用分数组去更新主数组。注意,在跑01背包时,由于已经选了当前主件,花费的范围要注意。

代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
vector<int> v[62];
int n,m,i,j,k,w[62],c[62],op[62],f[30002],g[30002];
int main()
{
    freopen("budget.in","r",stdin);
    freopen("budget.out","w",stdout);
    cin>>m>>n;
    for(i=1;i<=n;i++){
        cin>>w[i]>>c[i]>>op[i];
        c[i]*=w[i];
        if(op[i]) v[op[i]].push_back(i);
    }
    for(i=1;i<=n;i++){
        if(!op[i]){
            for(j=w[i];j<=m;j++) g[j]=f[j-w[i]]+c[i];
            for(j=0;j<v[i].size();j++){
                int x=v[i][j];
                for(k=m;k>=w[i]+w[x];k--) g[k]=max(g[k],g[k-w[x]]+c[x]);//在这里注意范围
            }
            for(j=1;j<=m;j++) f[j]=max(f[j],g[j]);
            memset(g,0,sizeof(g));
        }   
    }
    cout<<f[m]<<endl;
    fclose(stdin);
    fclose(stdout);
    return 0;
}

总结

没有想到还是因为想的不够细致,没有将DP的约束与状态分开,导致约束失效。

猜你喜欢

转载自www.cnblogs.com/LSlzf/p/11111572.html
t1