1. 程式人生 > >題解報告:hdu 2546 飯卡(01背包)

題解報告:hdu 2546 飯卡(01背包)

set div input 解題思路 結束 hdu 2546 代碼 sizeof 以及

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 解題思路:簡單的01背包。如果卡余額不小於5,那麽就可以買,先排序,對價格最貴的菜先不買,去買其他n-1個菜使得價格總和不超過m-5,這樣最後用5塊錢再來買一個價格最貴的菜即可使得消費最大,對應卡上的余額更少。
AC代碼:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1005
; 4 int n,m,vi[maxn],dp[maxn]; 5 int main(){ 6 while(~scanf("%d",&n)&&n){ 7 memset(dp,0,sizeof(dp)); 8 memset(vi,0,sizeof(vi)); 9 for(int i=0;i<n;++i)scanf("%d",&vi[i]); 10 sort(vi,vi+n);//排序 11 scanf("%d",&m); 12 if(m<5)printf("
%d\n",m); 13 else{ 14 for(int i=0;i<n-1;++i)//最後一個菜不挑選,留在最後買 15 for(int j=m-5;j>=vi[i];--j) 16 dp[j]=max(dp[j],dp[j-vi[i]]+vi[i]); 17 printf("%d\n",m-dp[m-5]-vi[n-1]);//減去一個最貴的菜 18 } 19 } 20 return 0; 21 }

題解報告:hdu 2546 飯卡(01背包)