hdoj 2546 飯卡 【01揹包】
阿新 • • 發佈:2019-02-09
飯卡
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16638 Accepted Submission(s): 5790
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
題目解析: 想要使卡上餘額最少,得保證最後一次買的菜最貴,(前提是你在最後一次買菜時卡上的前要大於或等於5)。假設購買菜之前卡上餘額為m,如果小於5元,那就不能買東西,所以卡里的錢不變;如果大於或等於5元,就用m-5表示可用餘額u,先花可用餘額,這樣就保證了在最後一次買菜前,你還有不少於5元的錢,然後用這最後的錢去買最貴的菜,就能使餘額最小了。(每買一個菜,在購買前都會先判斷餘額,不會出現一次買多個菜)。
程式碼:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int sum[1010];//所能購買的最大價值; int price[1010];//每個菜的價錢; int main() { int t; int n,i,j;//n是菜的數量; int m,u;//卡上的餘額,可用餘額; while(scanf("%d",&n),n) { memset(sum,0,sizeof(sum));//將sum陣列初始化為0; for(i=0;i<n;i++) { scanf("%d",&price[i]); } sort(price,price+n);//目的是找出最貴的菜,price[n-1]是最貴的菜; scanf("%d",&m); if(m<5)//餘額小於5時跳出; { printf("%d\n",m);//因不能購買,所以卡里的錢不變; continue; } u=m-5;//可用餘額,用可用餘額去買除了最貴的菜的剩餘的菜,能買多少就買多少。 for(i=0;i<n-1;i++)//(0----n-2)//除去最貴的菜的所有菜; { for(j=u;j>=price[i];j--) { sum[j]=max(sum[j],sum[j-price[i]]+price[i]); //保證在餘額不少於5的情況下購買最大價值。 } } //運算到這裡,我們已經求出可用餘額u所能購買的最大價值sum[u]。接下 //來卡里至少還有5元,而我們最貴的菜還沒有買,這是最後一次購買機會, //我們買最貴的菜,就能使卡里的餘額最小了。 printf("%d\n",m-sum[u]-price[n-1]); //可用餘額買的最大價值(除去最大菜價),加上最大菜價就是餘額能買到的最大價值,用餘額m(最開始的餘額)減去能買到的最大價值,卡里的餘額就最小了; } return 0; }