POJ 1787 Charlie's Change

題意:給定一個數P,要求用四種幣值爲1,5,10,25的硬幣拼成P,並且硬幣數要最多。

分析:這是一個多重揹包問題,但是要轉換一下思路,現在要求硬幣數量最多,那麼P是揹包容量,硬幣面值是cost,硬幣數量是weight。多重揹包問題加上used數組可以轉換爲完全揹包問題,這樣可以減小複雜度。還有就是要記錄各種面值的硬幣使用了多少次,這就需要記錄路徑。

代碼:

#include <iostream>
using namespace std;
#define INIT -99999

int P;
int dp[10001];
int used[10001];//使用used數組來標記used[j]達到金額j的時候,所使用的第i種鈔票的個數
int path[10001];
int cost[5] = {0,1,5,10,25};
int cnt[26];

int main(int argc, char **argv)
{
	while (scanf("%d%d%d%d%d",&P,&cnt[1],&cnt[2],&cnt[3],&cnt[4])!=EOF &&
		P|cnt[1]|cnt[2]|cnt[3]|cnt[4]!=0) {
			for(int i=1; i<=10001; ++i) {
				dp[i] = INIT;
			} 
			dp[0] = 0;
			memset(path,0,sizeof(path));
			path[0] = -1;
			for (int i=1; i<=4; ++i) {
				memset(used,0,sizeof(used));
				for (int j=cost[i]; j<=P; ++j) {
					if (	dp[j-cost[i]]!=INIT && dp[j]<dp[j-cost[i]]+1
						&& used[j-cost[i]]+1<=cnt[i]) {
							dp[j] = dp[j-cost[i]]+1;
							 used[j] = used[j-cost[i]] + 1; 
							  path[j] = j - cost[i]; 
					}
				}
			}
			if (dp[P] != INIT) {  

				memset(cnt,0,sizeof(cnt));  
				while (path[P] != -1) {  

					cnt[P-path[P]]++;  
					P = path[P];  
				}  
				printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",cnt[1],cnt[5],cnt[10],cnt[25]);  
			}  
			else printf("Charlie cannot buy coffee.\n"); 
	}
	system("pause");
	return 0;
}

94MS過~



發佈了29 篇原創文章 · 獲贊 46 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章