POJ1787 【完全背包+物品计数+路径输出】

您所在的位置:网站首页 poj1384 POJ1787 【完全背包+物品计数+路径输出】

POJ1787 【完全背包+物品计数+路径输出】

2023-03-13 03:53| 来源: 网络整理| 查看: 265

题意: 有1,5,10,25四种硬币,给每种硬币的数量和要组合成的价值,求刚好达到价值时用的硬币最多,然后还要输出具体的用的数量

前言: 一开始是偶然看见了kuangbin爷的题解说是完全背包+路径,很好奇啊。

思路(kuangbin爷代码 Orz): 一个完全背包,加个计数,加个路径。 因为题目要求是求一个max硬币数量,所以直观上我们感觉就是面值小的硬币用的越多越好,然后在dp更新的时候,基于小面值使用大面值。所以val数组是从小到大,目的是尽可能使用更多的小面值硬币达到dp数组是每次都是最多的。然而如果是求最小硬币数,直接就可以把面值数组掉一下头就好啦~ 突然有个问题(太弱就会瞎想): 有没有存在可能被给出的P面值没有被更新到,虽然dp数组判断条件是判断谁大,所以初始化0就好了(P>=1),一旦符合就是有符合的条件。所以是成立。

忽略以上的问题,利用完全背包的思想: 首先在更新的时候必须保证dp[j-val[i]]>=0的,第一枚硬币的更新是以 j-val[i] = 0为基础开始的,以至于dp数组才可以代表的是 j 面值的最大硬币数。所以初始化dp是负数。 然后加一个cnt,非常nice的一个想法。

具体写法: ①:我们可以开一个num数组去记录某价值下的某硬币的使用情况。 ②:我们可以开个pre数组去记录一下某 j 面值的前面的j-val[i],然后递归到0,中间的差值就是被使用价值的硬币,再开一个数组记录一下就好了。 除了这个方法,还有多重背包+路径;

贴一发挫code……….

#include #include #include #include #include using namespace std; #define eps 1e-8 typedef __int64 LL; const int N=+; int val[]={,,,}; int dp[N]; //在该面值的最大硬币数量 int num[]; int pre[N];//记录背包路径 int cnt[N];//每次更新是临时计数 int ans[]; //计数 int main() { int n; int t; bool flag=true; while() { scanf("%d",&t); for(int i=;icnt[j-val[i]])//首先dp[j-val[i]]>=0,因为要保证你前面那个是满足的 { dp[j]=dp[j-val[i]]+; cnt[j]=cnt[j-val[i]]+; pre[j]=j-val[i]; } } } if(dp[t]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3