饭卡Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 44141 Accepted Submission(s): 15106 Problem Description 电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
Input 多组数据。对于每组数据:
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元钱在去掉最贵的食物里找到能花的最大钱数
即背包容量为m-5,物品有n-1种(去掉最贵),这里物品的价值与体积相同,
求此背包能装的最大值,求出此值为dp[m-5],用m-dp[m-5]即买最后一次前能达到的最接近5的
dp[j]的含义:在钱数为j的时候所花的的最大钱数
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
int a[1005],dp[1005];
int main()
{
while(cin>>n && n)
{
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
cin>>m;
if(m<5)//不要忽略一开始钱数就小于5的情况
{
cout<<m<<endl;
continue;
}
memset(dp,0,sizeof dp);
for(int i=0;i<n-1;i++)
for(int j=m-5;j>=a[i];j--)
{
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}
cout<<m-dp[m-5]-a[n-1]<<endl;//总的钱m-去掉价格最高的
}
return 0;
}