poj 1787 Charlie's Change (多重背包+记录路径)***
2012-08-17 15:16
447 查看
http://poj.org/gotoproblem?pid=1787
(1)本题为一般的多重背包问题,亮点在于记录路径的方法,开了一个数组 pre[10010] 记录前一步的位置。调用时用 sum[30] 逐个累加即可(当然,这里的调用方法还有其他的各种方法)。
记录:
调用:
(2)多重背包一如既往,用数组 used[10010] 限制,转化为01背包(或是完全背包,只是形式有点像而已,不属于而这任何一类)。
(3)初始化问题:
1)将dp[i] 预处理为0。 dp[i] 表示 i 元最多用多少硬币 ,但它还有另一重意思,即 i 元可以用已有的硬币表示,其值为真和假(0和1)。换而言之,dp[10010] 完成了两个数组才能完成的任务。然而,第一种含义下,dp[0]=0, 第二种含义下, dp[0]=1,存在矛盾,真的要用两个数组才能完成么?
令 dp[0]=1 时有原因的,因为 dp[0] 的第一种含义并不重要,第二种含义与题目息息相关。
2)只需令 pre[0]=-1 即可;
(4)限制条件问题:
如果 dp[j] 未求或是太小,dp[j-b[i]] 已求,并且硬币还够用,则进入循环。
具体代码:
View Code
(1)本题为一般的多重背包问题,亮点在于记录路径的方法,开了一个数组 pre[10010] 记录前一步的位置。调用时用 sum[30] 逐个累加即可(当然,这里的调用方法还有其他的各种方法)。
记录:
pre[j]=j-b[i];
调用:
for(i=m;pre[i]!=-1;i=pre[i]) ans[i-pre[i]]++;
(2)多重背包一如既往,用数组 used[10010] 限制,转化为01背包(或是完全背包,只是形式有点像而已,不属于而这任何一类)。
(3)初始化问题:
1)将dp[i] 预处理为0。 dp[i] 表示 i 元最多用多少硬币 ,但它还有另一重意思,即 i 元可以用已有的硬币表示,其值为真和假(0和1)。换而言之,dp[10010] 完成了两个数组才能完成的任务。然而,第一种含义下,dp[0]=0, 第二种含义下, dp[0]=1,存在矛盾,真的要用两个数组才能完成么?
memset(dp, 0, sizeof(dp)); dp[0]=1;
令 dp[0]=1 时有原因的,因为 dp[0] 的第一种含义并不重要,第二种含义与题目息息相关。
2)只需令 pre[0]=-1 即可;
pre[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-b[i]] 已求,并且硬币还够用,则进入循环。
具体代码:
View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n, m;
int a[5], b[5]={0,1,5,10,25};
int dp[10010], used[10010];
int pre[10010];
int ans[30];
int main()
{
int i, j, k;
while(scanf("%d", &m)!=EOF)
{
for(i=1;i<=4;i++) scanf("%d", &a[i]);
if(!m&&!a[1]&&!a[2]&&!a[3]&&!a[4]) break;
memset(dp, 0, sizeof(dp));
memset(pre, 0, sizeof(pre));
dp[0]=1; // 表示 dp[0] 已求过
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;
}
相关文章推荐
- zoj2156 Charlie's Change 完全背包+路径记录
- POJ 1787 Charlie's Change (完全背包,记录路径)
- poj 1787 Charlie's Change【多重背包可行性+记录路径】
- poj 1787 Charlie's Change(多重背包路径记录)
- POJ 1787 Charlie's Change(多重背包+记录路径)
- zoj 2156 Charlie's Change(多重背包+倍增优化+记录路径)
- poj1787 Charlie's Change (多重背包+记录路径)
- POJ 1784 Charlie's Change 记录路径的多重背包
- POJ1787:Charlie's Change(记录路径的多重背包)
- zoj2156Charlie's Change 多重背包可行性问题+记录路径
- POJ_1787_Charlie'sChange(多重背包&&记录路径)
- UVA 624 记录路径的0-1背包
- CCCC 题目集 L3 001 凑零钱 【背包 + 记录路径 + 思维】
- oj1787Charlie's Change(多重背包+记录路径,每个包恰好被填满的基础上每个包的钱币的个数尽量多)
- poj 1787 背包+记录路径
- CodeForces - 864E Fire 背包+记录路径
- 0/1背包记录路径
- hdu6083 2017"百度之星"资格赛1004 度度熊的午饭时光(背包dp+记录路径)
- poj1787 Charlie's Change(多重背包+路径)
- POJ 1293 Duty Free Shop(背包记录路径)