# Greedy# Sorting# Iteration

e591 - 11264 - Coin Collector

🔗 前往 ZeroJudge 原題

題目描述

題目描述了 Sultan 在一個國家旅行,他想從銀行提取錢幣,並儘可能收集到最多種類的硬幣。銀行會優先給予面額最大的、小於等於剩餘金額的硬幣。題目要求計算 Sultan 在一次提款中最多可以獲得多少種類不同的硬幣。

解題思路

這題可以使用貪心演算法解決。由於銀行總是優先給予面額最大的硬幣,因此 Sultan 應該按照硬幣面額由大到小的順序考慮。

  1. 首先,對硬幣面額進行排序。
  2. 然後,從最大的硬幣開始,如果當前硬幣面額小於等於剩餘金額,則取出該硬幣,並更新剩餘金額和收集到的硬幣種類數量。
  3. 重複步驟 2,直到剩餘金額為 0 或所有硬幣都已考慮過。

程式碼中,total 記錄了已收集的硬幣總價值,ans 記錄了已收集的硬幣種類數量,a 記錄了上次收集的硬幣面額。每次迭代,如果當前硬幣 b 大於 total,則表示可以新增一種硬幣,ans 加 1,total 更新為 total + ba 更新為 b。如果 b 不大於 total 但大於 a,則表示可以替換掉之前收集的較小面額硬幣,total 更新為 total + (b - a)a 更新為 b

複雜度分析

  • 時間複雜度: O(n log n) (主要來自排序)
  • 空間複雜度: O(1)

程式碼

#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <stdio.h>
inline int read(){
	int a(0);
	char c('0');
	while(c>='0'){
		a=(a<<3)+(a<<1)+c-'0';
		c=getchar_unlocked();
	}
	return a;
}
inline void write(int x) {
	int stk[9],*ptr(&stk[0]);
	while(x){*ptr=x%10;x/=10;++ptr;}
	while(--ptr>=(&stk[0])){putchar_unlocked(*ptr+'0');}
}
int main(){
	int t=read(),n,a,b,total,ans;
	while(t--){
		n=read();
		ans=0;total=0;a=0;
		while(n--){
			b=read();
			if(b>total){
				++ans;
				total+=b;
				a=b;
			}
			else if(b>a){
				total+=(b-a);
				a=b;
			}
		}
		write(ans);
		putchar_unlocked('\n');
	}
}

Discussion