HDU 2546 饭卡(01背包)
题目代号:HDU 2546
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2546
饭卡
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 32321 Accepted Submission(s): 11167
Problem Description
电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
Input
多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。
n=0表示数据结束。
第一行为正整数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块钱,在ans-5的背包中能选择的价值最大是多少,dp[j]=max(dp[j],dp[j-a[i]]+a[i]);然后再减去价格最贵的菜,得到的值就是我门想要的结果;否则,如果卡上余额小于5块钱,那么买不了任何东西,所以原样输出即可(一开始我忘记了这种情况[#气哭])。
///delet.................................... # include <iostream> # include <cstring> # include <cstdlib> # include <cstdio> # include <string> # include <cmath> # include <ctime> # include <set> # include <map> # include <queue> # include <stack> # include <bitset> # include <vector> # include <fstream> # include <algorithm> using namespace std; # define eps 1e-8 # define pb push_back # define mp make_pair # define pi acos(-1.0) # define bug puts("H"); # define mem(a,b) memset(a,b,sizeof(a)) # define IOS ios::sync_with_stdio(false); # define FO(i,n,a) for(int i=n; i>=a; --i) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define INF 0x3f3f3f3f # define MOD 1000000007 /// 123456789 //# pragma comment(linker, "/STACK:1024000000,1024000000") typedef unsigned long long ULL; typedef long long LL; inline int Scan(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ///coding................................... int a[1005],dp[1005]; int main() { IOS; #ifdef FLAG freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif /// FLAG int n,ans; while(cin>>n,n) { mem(dp,0); FOR(i,1,n)cin>>a[i]; cin>>ans; sort(a+1,a+n+1); if(ans>=5) { FOR(i,1,n-1)FO(j,ans-5,a[i]) dp[j]=max(dp[j],dp[j-a[i]]+a[i]); cout<<ans-dp[ans-5]-a[n]<<endl; } else cout<<ans<<endl; } return 0; }