B-最小硬币问题

1.多重背包版

描述:

设有n种不同面值的硬币,各硬币的面值存于数组T[1:n]中。现要用这些面值的硬币来找钱。可以使用的各种面值的硬币个数存于数组Coins[1:n]中。
对任意钱数0≤m≤20001,设计一个用最少硬币找钱m的方法。
对于给定的1≤n≤10,硬币面值数组T和可以使用的各种面值的硬币个数数组Coins,以及钱数m,0≤m≤20001,计算找钱m的最少硬币数。

输入:

输入数据第一行中只有1个整数给出n的值,第2行起每行2个数,分别是T[j]和Coins[j]。最后1行是要找的钱数m。

输出:

输出数据只有一个整数,表示计算出的最少硬币数。问题无解时输出-1。

样例:

输入:
3
1 3
2 3
5 3
18
输出:
5

dp思路:

dp数组含义: dp[j]表示在找零钱数为j元时的最小硬币数量

第一步:首先假设我们持有1,3,5三种不同面值的硬币(数量先不讨论)。
第二步:对于0元钱找零,很显然我们不需要使用任何硬币,因此dp[0]=0
第三步:对于1元钱找零,我们只需要使用一枚1元硬币因此dp[1]=1
第四步:对于2元钱找零,我们可以在第三步的基础上再使用一枚1元硬币,此时dp[2]=dp[1]+1=2。
第五步:对于3元钱找零,我们可以在第四步的基础上再使用1枚1元硬币,此时dp[3]=dp[2]+1=3,我们还可以选择直接使用1枚3元硬币找零,此时dp[3]=1。因为是最小硬币,我们取1
第六步:经过推导我们可以发现,对于n元钱找零,我们往往是建立在j元钱找零的情况下再选择一枚合适的硬币dp[n]=dp[j]+1(j<n)。也就是说,我们想要对n元钱找零就是在找零j元的基础上再加上某一硬币即可,具体使用面值为几的硬币则需要一个个尝试。
dp[n]=dp[j]+1=dp[n-1]+1 || dp[n-3]+1 || dp[n-5]+1
第七步:我们将具体例子放大到题目
dp[n]=min(dp[n],dp[n-t[i]]+1) ; t[i]即对应着所有不同面值的硬币

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int t[105],c[105];
int dp[20010];
int main()
{int n;cin>>n;for(int i =0; i<n; i++)cin>>t[i]>>c[i];int p;cin>>p;memset(dp,inf,sizeof(dp));//初始化为无穷大dp[0] =0;//0元找零的情况需要标注for(int i = 0; i<n; i++) //使用前i种硬币for(int j = 1; j <= c[i]; j++)//第i种硬币选择几张for(int k = p; k >= t[i]; k--)//找零k元{dp[k]=min(dp[k],dp[k-t[i]]+1);}if(dp[p] >= inf)dp[p] =-1;cout<<dp[p]<<endl;
}

其实对于多重背包问题,我们往往最经典的是采用将其转换成01背包问题,或者01背包+完全背包问题(这里就不在赘述)下面是转换成01+完全背包的解法示例

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f;
int t[105],c[105];
int dp[200010];
int main(){int n;cin>>n;for(int i=1;i<=n;i++){cin>>t[i]>>c[i];}int m;cin>>m;for(int i=1;i<=m;i++){dp[i]=inf;}//注意不要用memset和fill初始化,不能ACdp[0]=0;for(int i=1;i<=n;i++){if(t[i]*c[i]>=m){//此时属于完全背包问题for(int j=t[i];j<=m;j++){dp[j]=min(dp[j],dp[j-t[i]]+1);}}else{//归为01背包问题for(int j=m;j>=t[i];j--){for(int k=1;k<=c[i];k++){if(j>=k*t[i])dp[j]=min(dp[j],dp[j-k*t[i]]+k);}}}}if(dp[m]==inf){cout<<"-1"<<endl;}else{cout<<dp[m]<<endl;}return 0;
}

2.完全背包版

不同于多重背包,完全背包的硬币数量是无限的。要解决完全背包,我们先回顾一下01背包的递推式推导

在使用二维数组的时候,递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

其实可以发现如果把dp[i - 1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);

于其把dp[i - 1]这一层拷贝到dp[i]上,不如只用一个一维数组了,只用dp[j](一维数组,也可以理解是一个滚动数组)。
于是可以得到递推式dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
在讲述完一维dp的递推之后,有一个很重要是事情便是遍历顺序,我们都知道在01背包的一维dp的遍历顺序中,物品的重量是要逆序遍历的,那么为什么要逆序的,正是因为如果正序遍历,后面的dp数组更新所需的前面dp数组的值是已经更新之后的,也就是存在一个物品被多次放入的情况。到这里,完全背包的思路也很显然了,无非就是更改一下物品重量的遍历顺序罢了。

将完全背包的解题思路应用到最小硬币问题中便是将找零的钱数从1开始正序遍历到p;递推式也很容易推导。对于t[i]元面值的硬币我们有取和不取两种办法,分别对应着dp[j](不取),以及dp[j-t[i]]+1(对应着取)
dp[j]=min(dp[j],dp[j-t[i]]+1);

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int t[12];//面值
int dp[20010];
int main()
{int n;cin>>n;for(int i =0; i<n; i++)cin>>t[i];int p;cin>>p;memset(dp,inf,sizeof(dp));//顺序1dp[0] =0;//顺序2for(int i=0;i<n;i++){for(int j=t[i];j<=p;j++){dp[j]=min(dp[j],dp[j-t[i]]+1);}}if(dp[p] >= inf)dp[p] =-1;cout<<dp[p]<<endl;
}

jk2002gyh

最小硬币问题(多重背包and完全背包)相关推荐

  1. 最少硬币找零系列问题(01背包,完全背包,多重背包动态规划)

    背包问题思路解决最小硬币找零系列问题. 一.01硬币找零问题(01背包) 给定不同面额的硬币 coins 和总金额 m.每个硬币最多选择一次.计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬 ...

  2. 背包问题(01背包,完全背包,多重背包(朴素算法二进制优化))

    写在前面:我是一只蒟蒻~~~ 今天我们要讲讲动态规划中~~最最最最最~~~~简单~~的背包问题 1. 首先,我们先介绍一下  01背包 大家先看一下这道01背包的问题   题目   有m件物品和一个容 ...

  3. 动态规划dp(带模板题の超易懂版):01背包,完全背包,分组背包,多重背包,混合背包

    动态规划dp(带模板题の超易懂版):01背包,完全背包,分组背包,多重背包 01背包 && 完全背包 && 分组背包 の 视频教程:https://www.bilibi ...

  4. 背包问题基础模型深度总结-文长慎入(01背包,完全背包,多重背包)

    先等一下,字多预警,密集恐惧症慎入,喂,你,就是你,小板凳搬好了吗,站久了可是会腿酸的 无节操地王婆卖瓜一下, 本文 深度好文 目录 先扯两句 0-1背包 其它类似的状态定义 1 2 小结 3  记忆 ...

  5. 背包问题教程-01背包,完全背包,多重背包,混合背包 收藏

    P01: 01背包问题 题目 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. 基本思路 这是最基础的背包问题,特点是:每种物品仅有 ...

  6. 01背包,完全背包,多重背包,分组背包的使用条件以及代码模板

    背包问题算是动态规划中的入门题目了,背包问题有很多种.背包九讲中讲的很清楚,我就不班门弄斧了,针对几种比较常见的背包问题,阐述一下它的使用前提和代码模板. 1.01背包问题 题目 有N 件物品和一个容 ...

  7. 01背包、完全背包、多重背包问题的C++实现及路径记录

    这里主要实现路径记录,只求最值问题移步 01背包.完全背包.多重背包问题的C++实现 以下均打印输出路径,即装入背包的物品序号,和最大值. 01背包问题 #include <iostream&g ...

  8. 01背包,完全背包,多重背包,混合背包,二维费用背包,分组背包,背包问题求方案数

    1 01背包问题 有 NNN 件物品和一个容量是 VVV 的背包.每件物品只能使用 一次. 第 iii 件物品的体积是 viv_ivi​,价值是 wiw_iwi​.求解将哪些物品装入背包,可使这些物品 ...

  9. 背包问题详解:01背包、完全背包、多重背包

    参考链接: http://www.cnblogs.com/fengty90/p/3768845.html http://blog.csdn.net/mu399/article/details/7722 ...

最新文章

  1. python 垃圾回收器_Python 垃圾回收机制详细
  2. 安卓高手之路之PackageManagerservice(二)
  3. 【Android 安全】DEX 加密 ( Application 替换 | 分析 Activity 组件中获取的 Application | ActivityThread | LoadedApk )
  4. Android 实现布局动态加载
  5. vs编译c语言停止工作运行库mt,vc++编译时运行库选择(/MT/MTd/MD/MDd)
  6. 啊哈算法系列(C语言、python、Java )
  7. Write operations are not allowed in read-only mode (FlushMode.MANUAL)
  8. au如何关闭预览编辑器_在线IDE开发入门之从零实现一个在线代码编辑器
  9. 【考研英语5500词】 —思维导图,建议收藏(四六级党也可入手)!!!
  10. linux和windows精简版,win7 64/86 超级精简版877MB -三蛋作品
  11. AD----如何将立创EDA元器件封装库导入AD库
  12. ACM中AC、WA、PE、RE分别是什么意思
  13. 智能客服搭建(5) - FreeSWITCH + mod_unimrcp + ESL 开发对接
  14. CCF [201703-1] 分蛋糕(C++)
  15. 第九周 作业管理系统成本估算
  16. WIN10系统-Deepin系统重装
  17. idea mysql可视化_IntelliJ IDEA 内置数据库管理工具实战
  18. 如何在 ubuntu 上安装 mercury mw150us 网卡驱动
  19. 剑指Offer II --- 2021/9/2
  20. 昂达v80 plus linux,昂达(ONDA)V80 Plus平板电脑整体性能评测-ZOL中关村在线

热门文章

  1. RecyclerView 教程,全面了解各种使用方法
  2. excel二进制移位运算_位运算-秦斌的博客-51CTO博客
  3. 空间转录组分析流程(使用Seurat对空间数据集进行分析)
  4. STM32 CAN TX无波形,原理图 TJA1042
  5. 一览科技CTO陈锡言:大模型阴影下的技术创业机会——链接大模型与用户|量子位·视点分享回顾...
  6. matlab 调用GPU运算
  7. 微服务和分布式的区别是什么?
  8. 机器学习算法系列(二十)-梯度提升决策树算法(Gradient Boosted Decision Trees / GBDT)
  9. 产品经理入职后要做的12件事
  10. 关于苹果iOS13的所有设计规范