1. 程式人生 > 其它 >【ACWing】653. 鈔票

【ACWing】653. 鈔票

技術標籤:AC 貪心、動態規劃與記憶化搜尋c++演算法

題目地址:

https://www.acwing.com/problem/content/655/

鈔票的面值有 100 , 50 , 20 , 10 , 5 , 2 , 1 100,50,20,10,5,2,1 100,50,20,10,5,2,1,給定一個金額,要求用那些面值的鈔票湊出這個金額,並且使得使用的鈔票數量最小。返回湊的方案。

思路是貪心,永遠儘量優先用金額大的鈔票即可。

演算法正確性證明:
首先容易知道方案一定存在。設 N = 100 x 1 + 50 x 2 + 20 x 3 + 10 x 4 + 5 x 5 + 2 x 6 + x 7 N=100x_1+50x_2+20x_3+10x_4+5x_5+2x_6+x_7

N=100x1+50x2+20x3+10x4+5x5+2x6+x7我們證明如果 N ≥ 100 N\ge 100 N100,則 x 1 > 0 x_1>0 x1>0。首先,容易知道 { x 2 ≤ 1 x 3 ≤ 2 x 4 ≤ 1 x 3 + x 4 ≤ 2 x 5 ≤ 1 x 6 ≤ 2 x 7 ≤ 1 x 6 + x 7 ≤ 2 \begin{cases} x_2\le 1\\ x_3\le 2\\ x_4\le 1\\x_3+x_4 \le 2\\x_5\le 1\\x_6\le 2\\x_7\le 1\\ x_6+x_7 \le 2\\\end{cases}
x21x32x41x3+x42x51x62x71x6+x72
那麼如果不允許用 100 100 100鈔票,能湊出的最大面額就是 50 + 2 ∗ 20 + 5 + 2 ∗ 2 = 99 < 100 50+2*20+5+2*2=99<100 50+220+5+22=99<100,這就矛盾了。所以必然有 x 1 > 0 x_1>0 x1>0。剩餘證明以此類推。

程式碼如下:

#include <iostream>
using namespace std;

int main() {
    int N;
cin >> N; cout << N << endl; int c[] = {100, 50, 20, 10, 5, 2, 1}; for (int i = 0; i < sizeof c / sizeof(int); i++) { printf("%d nota(s) de R$ %d,00\n", N / c[i], c[i]); N %= c[i]; } return 0; }

時空複雜度 O ( 1 ) O(1) O(1)