hdu 3449 有依赖的背包

背景:1——TL按照背包九讲的把没一个依赖组转用01背包转化成物品集合,然后又用分组背包的方法来做,超时。优化无果,借鉴别人思路ac。

正确写法思路:先不管必须选盒子这个前提,按照01背包的思想把物品选一次到thing[]数组中,然后再把再强项对每个数据都买盒子,这样thing中只有thing[box....v]能买起盒子,且thing[k]=thing[k-box]+0 ,盒子的价值是0.所以转移方程:F[j]=max{F[j],thing[k-box]} (F[j]表示不选盒子和盒子里的物品的价值,thing[k-box]表示选择盒子和盒子内的物品所能达到的最大价值)

题目注解见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#define INF 100009
using namespace std;
int thing[INF],F[INF];
int n,v,box,mi,co[20],wo[20],sum_box;



int main(void){
    while(~scanf("%d%d",&n,&v)){
        memset(F,sizeof(F));
        for(int i=0;i < n;i++){
            scanf("%d%d",&box,&mi);
            for(int j=0;j < mi;j++){
                scanf("%d%d",&co[j],&wo[j]);
            }
            memcpy(thing,F,sizeof(F));    //继承上次的状态。
            for(int i=0;i < mi;i++){    //在不考虑选择盒子的情况下,01背包式自由选择附件。
                for(int j=v;j >= co[i];j--){
                    thing[j]=max(thing[j],thing[j-co[i]]+wo[i]);
                }
            }
            for(int i=0;i <= v;i++) F[i]=max(F[i],thing[i-box]);  /*减去盒子费用的转移:这里其实是把,自由选择下的F[box...v],当做选了盒子之后的F[1...v-box]
        }                                                           这样就能满足:先必须选择一个盒子,再选择用01背包的方式选择一个物品的条件了*/
        printf("%d\n",F[v]);
    }
    return 0;
}


将附件集合转化为物品组的超时代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#define INF 100009
using namespace std;
int thing[INF],sum_box;

void zeroonebag(void){
     for(int j=0;j < mi;j++){
         for(int k=sum_box;k >= co[j];k--){
             thing[k]=max(thing[k],thing[k-co[j]]+wo[j]);
         }
     }
}

int main(void){
    while(~scanf("%d%d",&mi);
            sum_box=0;
            for(int j=0;j < mi;j++){
                scanf("%d%d",&wo[j]);
                sum_box+=co[j];
            }
            sum_box=min(v-box,sum_box);
            memset(thing,sizeof(thing));
            if(box >= v) continue;
            zeroonebag();    //用01背包将附件集合转化为物品组。
            for(int j=v;j >= 1;j--){
                for(int k=0;k <= sum_box;k++){
                    if(j-box-k >= 0) F[j]=max(F[j],F[j-box-k]+thing[k]);
                }
            }
        }
        printf("%d\n",F[v]);
    }
    return 0;
}

相关文章

什么是设计模式一套被反复使用、多数人知晓的、经过分类编目...
单一职责原则定义(Single Responsibility Principle,SRP)...
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强...
适配器模式将一个类的接口转换成客户期望的另一个接口,使得...
策略模式定义了一系列算法族,并封装在类中,它们之间可以互...
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,...