多重背包问题
来源:互联网 发布:如何删除mac上的照片 编辑:程序博客网 时间:2024/05/01 10:56
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2156
题意:charlie有四种硬币,价值分别为1,5,10,,25,给定每种价值硬币的个数,求出能够刚好买下coffee的硬币的个数,硬币应该尽可能的多,并且选出的硬币的价值之和要正好等于coffee的价值。
类型:多重背包问题
思路:1)在本题中最大的难点在于怎么记录每种硬币的个数。方法是构造一个数组pre,pre[j]=j-b[i],将pre初始化为0,然后将pre[0]初始化为-1。
2)用一个used数组表示该种硬币的使用情况,used[j]=used[j-b[i]]+1;当used大于该种硬币的数目时,那么就要开始不挑选本种硬币,开始下一层循环。
3)定义dp数组表示i元最多用多少枚硬币,同时也表示i元能否用已有的硬币表示,真为1,假为0,故首先将dp置为0,然后将dp[0]置为1。
4)约束条件为if((!dp[j]||dp[j-b[i]]+1>dp[j])&&dp[j-b[i]]&&used[j-b[i]]+1<=a[i]),表示dp[j]为求解,或者dp[j]不够大,并且dp[j-b[i]]不为0(能够用已有的硬币表示)同时,该 种硬币还足够,那么才能进入循环,进行更新。
#include<cstdio>
#include<iostream>#include<stdlib.h>
#include<string.h>
#include<algorithm>
#define N 10010
using namespace std;
int n,m;
int a[5],b[5]={0,1,5,10,25};
int dp[N];
int used[N];
int pre[N];
int ans[30];
int main()
{
int i,j,k;
while(scanf("%d",&m)!=EOF)
{
int count=m;
for(i=1;i<=4;i++)
{
scanf("%d",&a[i]);
count+=a[i];
}
if(!count) break;memset(dp, 0, sizeof(dp));
memset(pre, 0, sizeof(pre));
dp[0]=1;
pre[0]=-1;
for(i=1;i<=4;i++)
{
for(j=0;j<=m;j++)
used[j]=0;
for(j=b[i];j<=m;j++)
{
if((!dp[j]||dp[j-b[i]]+1>dp[j])&&dp[j-b[i]]&&used[j-b[i]]+1<=a[i])
{
dp[j]=dp[j-b[i]]+1;
used[j]=used[j-b[i]]+1;
pre[j]=j-b[i];
}
}
}
memset(ans,0,sizeof(ans));
if(dp[m])
{
for(i=m;pre[i]!=-1;i=pre[i])
ans[i-pre[i]]++;
printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", ans[1], ans[5], ans[10], ans[25]);
}
else printf("Charlie cannot buy coffee.\n");
}
return 0;
}
- 多重背包问题
- 多重背包问题
- 多重背包问题
- 多重背包问题
- P03: 多重背包问题
- 多重背包问题、、、
- P03: 多重背包问题
- 03多重背包问题
- 多重背包问题
- P03: 多重背包问题
- 多重背包问题
- P03: 多重背包问题
- 多重背包问题
- HDU2191多重背包问题
- POJ1014 多重背包问题
- poj2392 多重背包问题
- 多重背包问题
- 多重背包问题
- XIB中Cell出现警告消除方法
- Git避免每次远程交互都需要输入密码的设置
- LeetCode
- OOP版电子词典
- Java多态性详解——父类引用子类对象
- 多重背包问题
- Linux下好玩的命令
- vi/vim 使用方法讲解
- 2 个有序List的交集
- linux合并文件
- Centos6.5下安装mariadb
- poj-3414 Pots BFS
- linux主机之间传输数据
- BFS DFS 模板