# Dynamic Programming# Greedy# Array

d119 - 有獎徵答:換零錢

🔗 前往 ZeroJudge 原題

題目描述

題目要求計算給定金額的所有零錢組合數,零錢面額為 1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000。需要注意的是,題目要求排除輸入金額本身所使用的零錢組合。

解題思路

此題可以使用動態規劃來解決。程式碼中,a[i] 儲存了組成金額 i 的零錢組合數。程式碼預先計算了從 0 到 50000 的所有金額的組合數,然後對於每個輸入金額,直接從預先計算的 a 陣列中獲取結果,並減去 1 (排除輸入金額本身所使用的零錢組合)。 預計算的過程,實際上是使用貪心策略,逐步增加可用的零錢面額,並更新 a 陣列。例如,先使用 1, 5,再使用 1, 5, 10,以此類推。

複雜度分析

  • 時間複雜度: O(50000 + n),其中 n 是輸入的組數。預計算陣列 a 的時間複雜度為 O(50000),處理每組輸入的時間複雜度為 O(1)。
  • 空間複雜度: O(50001),用於儲存 a 陣列。

程式碼

#include <iostream>
#include <string>
using namespace std;
long long int a[50001];
int main(){
	for(int i=0;i<50001;++i)
		a[i]=1;
	for(int i=5;i<50001;++i)
		a[i]+=a[i-5];
	for(int i=10;i<50001;++i)
		a[i]+=a[i-10];
	for(int i=20;i<50001;++i)
		a[i]+=a[i-20];
	for(int i=50;i<50001;++i)
		a[i]+=a[i-50];
	for(int i=100;i<50001;++i)
		a[i]+=a[i-100];
	for(int i=200;i<50001;++i)
		a[i]+=a[i-200];
	for(int i=500;i<50001;++i)
		a[i]+=a[i-500];
	for(int i=1000;i<50001;++i)
		a[i]+=a[i-1000];
	for(int i=2000;i<50001;++i)
		a[i]+=a[i-2000];	
	string g;
	while(getline(cin,g)){
		if(g=="0")break;
		int sum=0,x=0;
		for(int i=0,gl=g.length();i<gl;++i){
			if(g[i]!=' '){
				x*=10;
				x+=g[i]-'0';
			}
			else{
				sum+=x;
				x=0;
			}
		}
		sum+=x;
		cout << a[sum]-1 << "\n";
	}
}

Discussion