揹包--飯卡

飯卡

電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷餘額。如果購買一個商品之前,卡上的剩餘金額大於或等於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

思路:我們先用一個揹包容量爲“所給價格減去5元”的揹包去裝菜,揹包裏東西裝得越多,餘額則越少。在揹包裝滿之後,飯卡里的餘額肯定是大於等於5的,根據題意可以知道只要飯卡大於等於5元,我們就可以買任何的菜,所以最後我們可以再減去一個最貴的菜,這樣飯卡的餘額就可以最少了。所以,需要有一步找到最貴的菜。 

AC代碼:

#include<stdio.h>
#include<string.h>
#define MAX 1010

int dp[MAX],cost[MAX];
int n,m;
int max,id;

int Max(int a,int b){
	return a>b?a:b;
}

void Init(){
	memset(dp,0,sizeof(dp));
	memset(cost,0,sizeof(cost));
	max = -1;
	id = -1;
} 

int ZeroOnePack(){

	int canCost = m-5;
	for(int i=0;i<n;i++){
		if(i==id)
			continue;
		for(int j=canCost;j>=cost[i];j--){
			dp[j]=Max(dp[j],dp[j-cost[i]]+cost[i]);
		}
	}
	return dp[canCost];
} 

int main(){
	while(scanf("%d",&n)!=EOF&&n!=0){
		Init();
		//輸入 
		for(int i=0;i<n;i++)
			scanf("%d",&cost[i]);
		scanf("%d",&m);
		
		if(m<5){//如果一開始給的錢就低於5元,那就什麼也買不了 
			printf("%d\n",m);
			continue;
		}
		//m>5元則進行下面操作 
		for(int i=0;i<n;i++){//挑出最大的那個菜 
			if(max<cost[i]){
				max=cost[i];
				id=i;
			}
		}
		cost[id] = -1; 
		//輸出 
		int a = ZeroOnePack();//找出最大花銷 前提爲剩下不小於5元 
		int v = m-a-max; //v表示最終可以到達的最小金額 
		printf("%d\n",v);
	}
	return 0;
}

 

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