poj 1787 Charlie's Change
2013-07-06 22:30
351 查看
思路: 多重背包
分析:
1 题目给定的数据明显就是多重背包,但是题目有个难点就是输出路径,0/1背包里面有输出路经的方法,做法做法是通过记录前面的状态
2 这一题还要求输出每种硬币的个数,那么这边利用mark数组,mark[i][0] = pos 表示的是当前这个状态是取的是第pos个物品,mark[i][pos] = x;表示的是当前这个状态增加了x个物品
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 10010;
const int N = 5;
const int INF = 0x3f3f3f3f;
int v
= {0,1,5,10,25};
int sum , num
, dp[MAXN];
int ans
, path[MAXN] , mark[MAXN]
;
void zeroOnePack(int pos , int k , int cost , int weight){
for(int i = sum ; i >= cost ; i--){
dp[i] = max(dp[i] , dp[i-cost]+k);
if(dp[i] == dp[i-cost]+1){
path[i] = i-cost;
mark[i][0] = pos;
mark[i][pos] = k;
}
}
}
void completePack(int pos , int cost , int weight){
for(int i = cost ; i <= sum ; i++){
dp[i] = max(dp[i] , dp[i-cost]+1);
if(dp[i] == dp[i-cost]+1){
path[i] = i-cost;
mark[i][0] = pos;
mark[i][pos] = 1;
}
}
}
void multiplePack(int pos , int cost,int weight,int amount){
if(cost*amount >= sum){
completePack(pos , cost , weight);
return;
}
int k = 1;
while(k < amount){
zeroOnePack(pos , k , k*cost , k*weight);
amount -= k;
k *= 2;
}
zeroOnePack(pos , amount , amount*cost , amount*weight);
}
int main(){
while(scanf("%d",&sum)){
scanf("%d%d%d%d",&num[1],&num[2],&num[3],&num[4]);
if(!(sum+num[1]+num[2]+num[3]+num[4]))
break;
for(int i = 0 ; i < MAXN ; i++)
dp[i] = -INF;
dp[0] = 0;
for(int i = 1 ; i <= 4 ; i++)
multiplePack(i , v[i],v[i],num[i]);
if(dp[sum] < 0)
puts("Charlie cannot buy coffee.");
else{
int pos = sum;
memset(ans , 0 , sizeof(ans));
while(pos){
int tmp = mark[pos][0];
ans[tmp] += mark[pos][tmp];
pos = path[pos];
}
printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",ans[1],ans[2],ans[3],ans[4]);
}
}
return 0;
}
分析:
1 题目给定的数据明显就是多重背包,但是题目有个难点就是输出路径,0/1背包里面有输出路经的方法,做法做法是通过记录前面的状态
2 这一题还要求输出每种硬币的个数,那么这边利用mark数组,mark[i][0] = pos 表示的是当前这个状态是取的是第pos个物品,mark[i][pos] = x;表示的是当前这个状态增加了x个物品
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 10010;
const int N = 5;
const int INF = 0x3f3f3f3f;
int v
= {0,1,5,10,25};
int sum , num
, dp[MAXN];
int ans
, path[MAXN] , mark[MAXN]
;
void zeroOnePack(int pos , int k , int cost , int weight){
for(int i = sum ; i >= cost ; i--){
dp[i] = max(dp[i] , dp[i-cost]+k);
if(dp[i] == dp[i-cost]+1){
path[i] = i-cost;
mark[i][0] = pos;
mark[i][pos] = k;
}
}
}
void completePack(int pos , int cost , int weight){
for(int i = cost ; i <= sum ; i++){
dp[i] = max(dp[i] , dp[i-cost]+1);
if(dp[i] == dp[i-cost]+1){
path[i] = i-cost;
mark[i][0] = pos;
mark[i][pos] = 1;
}
}
}
void multiplePack(int pos , int cost,int weight,int amount){
if(cost*amount >= sum){
completePack(pos , cost , weight);
return;
}
int k = 1;
while(k < amount){
zeroOnePack(pos , k , k*cost , k*weight);
amount -= k;
k *= 2;
}
zeroOnePack(pos , amount , amount*cost , amount*weight);
}
int main(){
while(scanf("%d",&sum)){
scanf("%d%d%d%d",&num[1],&num[2],&num[3],&num[4]);
if(!(sum+num[1]+num[2]+num[3]+num[4]))
break;
for(int i = 0 ; i < MAXN ; i++)
dp[i] = -INF;
dp[0] = 0;
for(int i = 1 ; i <= 4 ; i++)
multiplePack(i , v[i],v[i],num[i]);
if(dp[sum] < 0)
puts("Charlie cannot buy coffee.");
else{
int pos = sum;
memset(ans , 0 , sizeof(ans));
while(pos){
int tmp = mark[pos][0];
ans[tmp] += mark[pos][tmp];
pos = path[pos];
}
printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",ans[1],ans[2],ans[3],ans[4]);
}
}
return 0;
}
相关文章推荐
- POJ 1787 - Charlie's Change(完全背包+路径记录)
- POJ-1787 Charlie's Change( 多重背包记录方案)
- POJ 1787 Charlie's Change / 完全背包
- 【POJ】1787 Charlie's Change(完全背包)
- Charlie's Change POJ - 1787
- Charlie's Change(POJ-1787)
- POJ 题目1787 Charlie's Change(完全背包)
- POJ-1787 Charlie's Change (完全背包+输出方案 入门题)
- poj 1787 Charlie's Change(完全背包 或 多重背包 记录路径)
- poj 1787 Charlie's Change(打印路径的多重背包 ->交易数量最大化)
- POJ--1787--Charlie's Change--背包变形
- poj 1787 Charlie's Change
- POJ 1787 Charlie's Change
- POJ 1787 Charlie's Change
- poj 1787 Charlie's Change【多重背包可行性+记录路径】
- poj 1787 Charlie's Change
- 动态规划,多重背包,保存路径,用完全背包的方法做多重背包(Charlie's Change,poj 1787)
- poj1787 Charlie's Change (多重背包+记录路径)
- POJ 1787 Charlie's Change 最多金币
- POJ 1787 Charlie's Change 背包问题