HDOJ 2546 飯卡 【0 1 揹包】

飯卡

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 17489    Accepted Submission(s): 6087


Problem Description
電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷餘額。如果購買一個商品之前,卡上的剩餘金額大於或等於5元,就一定可以購買成功(即使購買後卡上餘額爲負),否則無法購買(即使金額足夠)。所以大家都希望儘量使卡上的餘額最少。
某天,食堂中有n種菜出售,每種菜可購買一次。已知每種菜的價格以及卡上的餘額,問最少可使卡上的餘額爲多少。
 

Input
多組數據。對於每組數據:
第一行爲正整數n,表示菜的數量。n<=1000。
第二行包括n個正整數,表示每種菜的價格。價格不超過50。
第三行包括一個正整數m,表示卡上的餘額。m<=1000。

n=0表示數據結束。
 

Output
對於每組輸入,輸出一行,包含一個整數,表示卡上可能的最小余額。
 

Sample Input
1 50 5 10 1 2 3 2 1 1 2 3 2 1 50 0
 

Sample Output
-45 32
題目鏈接:HDOJ 2546 飯卡 【0 1 揹包】

思路:不足 5 元,什麼都買不到;餘額大於 5 時,先用 5 元買最貴的,再用剩餘的錢儘可能多的買(即爲 0 1 揹包問題 )

需要注意每樣只能買一次,最後餘額 = 總金額 - 最貴的菜 - 去掉5元后能買到的最貴的菜 

已AC代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 1100
#define Max(x,y) (x>y?x:y)
using namespace std;

int dp[1100],price[M];

int main()
{
	int n,m,i,j;
	while(scanf("%d",&n),n)
	{
		memset(price,0,sizeof(price));
		memset(dp,0,sizeof(dp));
		
		for(i=0;i<n;++i)
			scanf("%d",&price[i]);
		scanf("%d",&m);
		if(m<5)//餘額小於5,什麼都不能買 
		{
			printf("%d\n",m);
			continue;
		}
		sort(price,price+n);//price[n-1] 爲最貴的菜 
		int MAX=m-5;
		for(i=0;i<n-1;++i)
			for(j=MAX;j>=price[i];--j)
				dp[j]=Max(dp[j],dp[j-price[i]]+price[i]);
		
		int s=m-price[n-1]-dp[MAX];//餘額=總金額-最貴的菜-去掉5元后能買到的最貴的菜 
		printf("%d\n",s);
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章