HDOJ2844-Coins(DP)
2015-05-05 20:39
204 查看
题意:你有n种面值的硬币,告诉你每种硬币的数量,问这些硬币能拼成多少不超过m的面额。
思路:多重背包。当某种硬币的总额大于背包容量时进行完全背包,否则进行二进制拆分进行01背包。最后统计f[i]==i的数量,即恰好能凑出金额为i的情况总数。详解请参考背包九讲。
代码如下:
思路:多重背包。当某种硬币的总额大于背包容量时进行完全背包,否则进行二进制拆分进行01背包。最后统计f[i]==i的数量,即恰好能凑出金额为i的情况总数。详解请参考背包九讲。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int f[100010]; int v[105],s[105];//面值,数量 int max(int x,int y) { return x>y?x:y; } void work(int n,int m) { int i,j,k,t,ans; memset(f,0,sizeof(f)); for(i=0;i<n;i++) scanf("%d",&v[i]); for(i=0;i<n;i++) scanf("%d",&s[i]); for(i=0;i<n;i++) { if(v[i]*s[i]>=m) { //若某种金币的总金额大于总价,则直接进行完全背包 for(j=v[i];j<=m;j++) f[j]=max(f[j],f[j-v[i]]+v[i]); } else { k=1; while(k<s[i]) { //将物品进行二进制拆分,进行01背包操作 for(j=m;j>=v[i]*k;j--) f[j]=max(f[j],f[j-v[i]*k]+v[i]*k); s[i]-=k; k<<=1; } //对二进制拆分后剩下的物品进行01背包 for(j=m;j>=v[i]*s[i];j--) f[j]=max(f[j],f[j-v[i]*s[i]]+v[i]*s[i]); } } ans=0; for(i=1;i<=m;i++) ans+=(f[i]==i); printf("%d\n",ans); } int main() { int n,m; while(scanf("%d%d",&n,&m),n||m) work(n,m); return 0; }
相关文章推荐
- 暑期dp46道(37) HDOJ 2844 COINS
- hdoj 2844 Coins【多重背包】【dp】
- HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)
- hdu 2844 Coins(dp 多重背包 二进制优化)
- HDOJ 2844 Coins
- hdoj-2844-Coins【多重背包】
- (DP,多重背包) Coins --HDOJ
- hdu 2844 Coins(DP, 背包)
- HDU - 2844 - Coins (多重背包,dp)
- Coins (poj 1742 && hdu 2844 DP)
- hdoj 2844 Coins
- Coins - HDU 2844 背包dp
- HDOJ-----1398---Square Coins---简单DP
- HDOJ题目2844 Coins(二维多重背包)
- HDU 2844 Coins (多重背包问题DP)
- hdu 2844 coins DP多重背包
- Coins (poj 1742 && hdu 2844 DP)
- hdu 2844 Coins(dp 多重背包)
- hdoj 2844 Coins(多重背包)
- 【HDOJ】2844 Coins