0
点赞
收藏
分享

微信扫一扫

动态规划(Dynamic Programming)例题1 LeetCode 322 Coin Change

想溜了的蜗牛 2022-01-10 阅读 49

翻译工作

给你一个数组,元素代表不同面值的硬币,一个整数,代表总钱数。用最少的硬币凑出总钱数,若不能凑出总钱数则返回-1。

你可能需要给出一系列特定的面值;

示例1:

输入:coins = [1,2,5],amount =11

输出:3

解释:11=5+5+1

示例2:

输入:coins = [2],amount = 3

输入:-1

示例3:

输入:coins = [1],amount = 0

输出:0

方法论:

以coins=[2,5,7],m=27为例

1.确定状态

数组f[i]/f[i][j]代表什么?

​​确定状态要有2个意识:1)最后一步 2)子问题

1)最后一步

假设最优策略是K枚硬币组成,即a1,a2,a3,……ak,a1+……ak = 27

 27-akak
K-1枚硬币最后一枚

注:2个关键

a.不关心前面的硬币是怎么拼出27-ak的(可能1种可能100种),甚至还不知道ak和K,但能确定前面的硬币拼出了27-ak。

b.因为是最优策略,所以拼出27-ak的硬币数一定是最优解。

2)子问题

用最少的硬币可以拼出27-ak。

设f[x]表示永最少硬币拼出x,ak取值为2,5,7,m=27

f[27]的取值可能为f[27-2]+1,f[27-5]+1,f[27-7]+1,由题取

f[27] = min{ f[27-2]+1,f[27-5]+1,f[27-7]+1}

2.转移方程

f[x]代表拼出x的最少硬币数

对于任意x,有f[x] = min{ f[x-2]+1,f[x-5]+1,f[x-7]+1}

3.初始条件,边界情况

f[0] = 0,f[x] = 正无穷表示当前硬币拼不出x

4.计算顺序

初始f[0] = 0

计算f[1],f[2]……f[27]

示例

#include<iostream>
#include<malloc.h>

using namespace std;

//LintCode;Coin Change
//3种硬币2元 5元 7元,买一本书27元
//如何用最少的硬币组合正好付清,不需要对方付清f(x)表示买一本27元的书凑出最少的硬币


/******66656565{2,5,7} *** 27*/
int CoinChange(int A[], int m) {
int MAXN = 32001;
int *f = new int[m+1];
f[0] = 0;
int lenA = 0;
for (int i = 0; A[i] >= 0; i++) {
lenA++;
}
int i, j;
for (i = 1; i <= m; i++) { //1 2 3...m
f[i] = MAXN;
for ( j = 0; j < lenA; j++) { //2 5 7
if (i >= A[j] && A[i - A[j]] != MAXN) { //所需金额大于面值且当前面值能凑出所需金额
f[i] = f[i] < (f[i - A[j]] + 1) ? f[i] : (f[i - A[j]] + 1) ;
}
}
}
if (f[m] == MAXN) {
f[m] = -1;
}
return f[m];
}

int main() {
//Coinchange
int A[] = { 2,5,7 };
int m = 27;
cout<<CoinChange(A,m);
return 0;
}
举报

相关推荐

0 条评论