飯卡
某天,食堂中有n種菜出售,每種菜可購買一次。已知每種菜的價格以及卡上的餘額,問最少可使卡上的餘額爲多少。
第一行爲正整數n,表示菜的數量。n<=1000。
第二行包括n個正整數,表示每種菜的價格。價格不超過50。
第三行包括一個正整數m,表示卡上的餘額。m<=1000。
n=0表示數據結束。
思路:不足 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;
}