[poj1742]Coins——多重背包优化DP

题目大意:

给定n个物品,第i个物品价值为a[i],数量为c[i],求可以组成的小于m的价值的个数。

思路:

好像n,m的范围比较大,暴力跑二进制优化的多重背包是可以卡过去的。但是有一种 O(nm) O ( n m ) 的方法来优化多重背包,即在枚举体积的时候我们按照完全背包来顺序枚举,完全背包里的枚举体积是可以满足重复选择同意物品的,但是由于每一种物品有自己的数量,所以我们对于每一种体积都记录剩余第i种物品的最大数量,这样就可满足不超出物品数量的限制了。
注意在用滚动数组的时候要把上一层的状态先全部转移到第i层才可以开始DP。

/*=====================
 * Author : ylsoi
 * Problem : Coins
 * Algorithm : DP
 * Time : 2018.5.5
 * ==================*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<climits>
using namespace std;
void File(){
    freopen("C1.in","r",stdin);
    freopen("C1.out","w",stdout);
}
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
#define MREP(i,x) for(register int i=beg[x];i;i=E[i].last)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define inf INT_MAX
const int maxn=100+10;
const int maxm=1e5+10;
int n,m,a[maxn],c[maxn],dp[maxm];
int main(){
    File();
    while(~scanf("%d%d",&n,&m)){
        if(n==0 && m==0)break;
        memset(dp,-1,sizeof(dp));
        dp[0]=0;
        REP(i,1,n)scanf("%d",&a[i]);
        REP(i,1,n)scanf("%d",&c[i]);
        REP(i,1,n){
            REP(j,0,m){
                if(dp[j]>=0)dp[j]=c[i];//这里即把上一层的状态都转移下来。
                else if(j>=a[i] && dp[j-a[i]]>0)dp[j]=dp[j-a[i]]-1;
            }
        }
        int ans=0;
        REP(i,1,m)ans+=(dp[i]>=0);
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值