poj1787-多重背包(基于完全背包)

来源:互联网 发布:汉诺塔递归算法思想 编辑:程序博客网 时间:2024/04/29 09:01

这题一拿到看明显用多重背包来做,之后用多重背包的二进制优化来做,给跪了,没倒腾出来,之后直接度娘之,看到大神代码说是多重背包可以用完全背包来做,而我的二进制优化就相当于01背包。看来还是看资料看的不仔细啊,要改。(不过有看大神代码说是用母函数的多项式展开来做,表示先做备忘,之后做数论在一起看吧)

这题背包的容量为价值,背包的总价值为加入的硬币数,用used[ ]数组来控制次数(由多重背包转化成完全背包),path来保存的上一个的总价值 path[v]=v-val[i];之后就ok了吧。

上代码:

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int maxn=10010;const int INF=0x3f3f3f3f;int used[maxn];int dp[maxn];int path[maxn];int cnt[4];int val[4]={1,5,10,25};int main(){    //freopen("int.txt","r",stdin);    while(1){        int n,sum=0;        scanf("%d",&n);        for(int i=0;i<4;i++){            scanf("%d",&cnt[i]);            sum+=cnt[i]*val[i];        }        memset(dp,-INF,sizeof(dp));        memset(path,0,sizeof(path));        path[0]=-1;        dp[0]=0;        if(!n&&!sum)break;        for(int i=0;i<4;i++){            memset(used,0,sizeof(used));            for(int v=val[i];v<=n;v++){                if(dp[v-val[i]]+1>dp[v]&&dp[v-val[i]]>=0&&used[v-val[i]]<cnt[i]){                    dp[v]=dp[v-val[i]]+1;                    used[v]=used[v-val[i]]+1;                    path[v]=v-val[i];                }            }        }        int ans[100];        memset(ans,0,sizeof(ans));        if(dp[n]<0){            printf("Charlie cannot buy coffee.\n");        }        else {            while(path[n]!=-1){                ans[n-path[n]]++;                n=path[n];            }            printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", ans[val[0]], ans[val[1]], ans[val[2]], ans[val[3]]);        }    }    return 0;}


0 0