[Aizu] DPL_1_A: Coin Changing Problem

题目

传送门: DPL_1_A: Coin Changing Problem

概述

使用面额为 d 1 d_{1} d1, d 2 d_{2} d2, …, d m d_{m} dm的硬币找出可以凑出 n n n美分的最小硬币数. 硬币可以使用任意次数

输入

n n n m m m
d 1 d_{1} d1 d 2 d_{2} d2 . . . ... ... d m d_{m} dm

两个整数 n n n m m m在第一行中给出, 可以使用的硬币面额在第二行中给出

输出

输出最小的硬币数

约束条件

  • 1 ≤ n ≤ 50000 1 \leq n \leq 50000 1n50000
  • 1 ≤ m ≤ 20 1 \leq m \leq 20 1m20
  • 1 ≤ 硬 币 面 额 ≤ 10000 1 \leq 硬币面额 \leq 10000 110000
  • 所有的硬币面额都不相同, 绝对包含面额为1的硬币

样例输入1

55 4
1 5 10 50

样例输出1

2

样例输入2

15 6
1 2 7 8 12 50

样例输出2

2

样例输入3

65 6
1 2 7 8 12 50

样例输出3

3

求解

分析

  第一眼看成贪心问题, 不过想着它放在动态规划的题目中, 至少要用动态规划的思路去解题, 然后还是以贪心的原理设计动态规划的关系式的.
  dp[x] 表示x美分至少需要的硬币数量, 那么就有dp[0] = 0; dp[i] = dp[i - D[j]] + 1; 表示0美分需要0个硬币, D[j]表示小于等于i的最大硬币面额, 然后i美分就等于i-D[j]的硬币数加上1个硬币(面额D[j]), 然后在第二个样例输入中果断出错.
  分析, 发现按照我的思路, 那么15 = 12 + 2 + 1, 而正确结果是15 = 8 + 7, 所以我在第二个关系式中, 不应该固定D[j]的值, 而是应该取所有面额小于等于i的硬币进行计算, 找出最小的一个.
  dp[i] 先赋值一个最大值, 然后在所有的小于i的硬币中进行处理 dp[i] = min(dp[i], dp[i - D[j]] + 1);

设计

  dp[x] 表示x美分最少需要的硬币个数, 它具有如下关系式

dp[0] = 0; // 0美分需要0个硬币
dp[i] = min(dp[i], dp[i - D[j]] + 1); // i美分需要min{ i-D[j]美分的硬币数+1 } 举个例子 样例2中, dp[15], 可以使用dp[15 - 12] + 1 = dp[3] + 1 = 3; 也可以使用dp[15 - 8] + 1 = dp[7] + 1 = 2; 等等, 找到最小的硬币数量

编码

#include <bits/stdc++.h>
using namespace std;
#define MAX_N 50005
#define MAX_M 25

int n, m;
int D[MAX_M];
int dp[MAX_N];

int main(void) {
	scanf("%d %d", &n, &m);
	for (int i = 0; i < m; i++) {
		scanf("%d", &D[i]);
	}
	sort(D, D + m, std::greater<int>());
	dp[0] = 0;
	int i, j;
	for (i = 1; i <= n; i++) {
		dp[i] = INT_MAX;
		for (j = 0; j < m; j++) {
			if (i >= D[j])
				dp[i] = min(dp[i - D[j]] + 1, dp[i]);
		}
	}
	printf("%d\n", dp[n]);
}

结果

在这里插入图片描述

总结

不要第一眼看上去挺简单就不去分析样例, 不然会做很多无用功的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值