目录
一、经典问题
- 面值为1元、2元、5元的硬币若干,如何用最少的硬币凑够11元
(一)分析
采用dp数组,当金额为i的时候,至少需要dp[i]枚硬币凑出
(二)方法一:递归
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 100000000
int change(int _S)
{
if (_S == 0)
return 0;
else if(_S < 0)
return INF;
else if (_S == 1)
return 1;
else
{
int ret = 0;
//有三种面额的硬币分别是:1 2 5
ret = min(1 + change(_S - 1), min(1 + change(_S - 2), 1 + change(_S - 5)));
return ret;
}
}
int main()
{
int S;//表示要凑出的金额
cin >>S;
int min = change(S);
cout << min;
return 0;
}
(三)方法二:动态规划
- 状态转移方程
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int change(int _S)
{
vector<int>dp(_S+1,_S);
//dp[i]表示当目标金额为i的时候,至少需要dp[i]个硬币
//当目标金额为_S的时候,那么有0到_S,所以dp数组的大小为_S+1
// 当要凑出金额为_S的时候,最坏的情况是全部用面额为1的硬币,则需要硬币数为_S,所以初始化为_S
dp[0] = 0;//目标金额为0的时候,需要的硬币数量是0
dp[1] = 1;//目标金额为1的时候,需要的硬币数量是1
for (int i = 2; i < dp.size(); i++)
{
if (i - 1 >= 0)
dp[i] = min(dp[i], 1 + dp[i - 1]);
if (i - 2 >= 0)
dp[i] = min(dp[i], 1 + dp[i - 2]);
if (i - 5 >= 0)
dp[i] = min(dp[i], 1 + dp[i - 5]);
}
return dp[_S] ;
}
int main()
{
int S;//表示要凑出的金额
cin >> S;
int min = change(S);
cout << min;
return 0;
}
二、崔迪凑硬币
NC21534 | 崔迪凑硬币 |
(一)题目描述
- 崔迪有面值为1,2,...,n的硬币,每种无限个。现在崔迪要从中随意选择一些硬币,凑出的总价值为S。(允许每种硬币选多个)现在崔迪需要挑选的最少硬币个数是多少?
(二)输入描述
第一行输入两个整数n,S,分别代表硬币最大面值,和需要凑出的总价值S
(三)输出描述
直接输出最少需要选择的硬币个数
(四)代码
#include<iostream>
using namespace std;
int main()
{
int n, s;//硬币最大面值和凑出目标值
cin >> n >> s;
int k = s / n;
if (s % n == 0)
cout << k << endl;
else
cout << k + 1 << endl;
return 0;
}