DP经典应用(五)硬币问题
来源:互联网 发布:科怀莱昂纳德体测数据 编辑:程序博客网 时间:2024/06/06 09:47
问题描述:
题目:有n种硬币,面值分别为V1,V2,…Vn,每种都有无限多。给定非负整数S,可以选用多少个硬币,使得面值之和恰好为S?输出硬币数目的最小值和最大值
分析:
按照解决动态规划的前3个步骤我们进行分析:
1.刻画一个最优解的结构特征:
定义minv[i]和maxv[i]分别为面值为i时的最少硬币数目和最多硬币数目。
而minv[0] = max[0] = 0;这就是边界值,因为面值为0时,什么面值的硬币都不能选。2.递归地定义最优解的值:
把每个面值看做一个点,表示还需凑足的面值,则初始状态为S,目标状态为0。
有两个状态
1.不使用一个硬币,那么还是minv[i] , maxv[i]
2.使用一个硬币,则状态转移到 i - Vj 。两者之一。
那么状态转移方程为:
minv[i] = min( minv[i] , minv[i-V[j]]+1);
maxv[i] = max(maxv[i] , maxv[i-V[j]+1);3.计算最优解的值,采用自底向上的递推法。
- 4.利用计算出的信息构造出一个最优解(就是下面代码中的打印解的部分)
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 100+5;const int INF = 100000000;int V[maxn],maxv[maxn],minv[maxn];int n,s;/*打印解*/void print_ans(int* d,int s){ for(int i=1; i<=n; i++) { if(s>=V[i] && d[s]==d[s-V[i]]+1) { printf("%d ",i); print_ans(d,s-V[i]); break; } }}int main(){ scanf("%d%d",&n,&s); for(int i=1; i<=n; i++) { scanf("%d",&V[i]); } minv[0] = maxv[0] = 0; for(int i=1; i<=s; i++) { minv[i] = INF; maxv[i] = -INF; } for(int i=1; i<=s; i++) { for(int j=1; j<=n; j++) { if(i >= V[j]) { minv[i] = min(minv[i],minv[i-V[j]]+1); maxv[i] = max(maxv[i],maxv[i-V[j]]+1); } } } printf("%d %d\n",minv[s],maxv[s]); print_ans(minv,s); printf("\n"); print_ans(maxv,s); return 0;}
注意打印最优解时要及时break;
0 0
- DP经典应用(五)硬币问题
- 硬币问题 经典dp
- 硬币问题(经典dp)
- 硬币问题(DP)
- 入门经典--硬币问题dp递归加递推
- HDU2069 & UVA 674 Coin Change(换硬币 dp 入门经典水题,背包问题)
- DP-硬币问题(一维)
- 【dp】最少硬币问题
- DP 换硬币问题
- dp 硬币找零问题
- dp 之硬币问题
- 紫书dp 硬币问题
- DP经典应用(一)数字三角形问题
- DP经典应用(二)最长递增子序列问题
- 【经典算法】:硬币组成问题
- 硬币找零(dp)
- DP DAG 9-3硬币问题(算法竞赛入门经典p162)
- 算法——硬币选择问题(dp、贪心)
- SOA与基于CDIF的API联动
- Redis底层数据结构之字典
- NBUT [1223] Friends number
- Linux内核如何装载和启动一个可执行程序
- netty学习笔记(2)_tcp拆包/粘包问题
- DP经典应用(五)硬币问题
- Rigidbody
- Spring框架学习(3):spring属性配置的细节
- jQuery学习笔记之DOM节点操作
- 《Xception: Deep Learning with Depthwise Separable Convolutios》笔记
- 2017年蓝桥杯——小题总结
- 即时搜索的input和propertychange方法的优点
- 2017回顾过往(分享近期读的几本书)
- 自定义--随机数(4位)