题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2546
这是一道01背包的变体。题目加了限制条件,当卡上金额大于等于5元时才能购买成功,我们不妨将这里的5元视为“0“,因为在DP过程中金额不能低于5,所以最后要用到的结果应该是dp[m-5]。既然我们保证了余额一直是大于等于5的,那么最后还能购买一次,所以,我们将最贵的一样菜留在最后,在DP的过程结束之后再购买,这样就能保证最后的余额最少。还有就是当输入m<5时直接输出m,当所有 菜相加小于等于m-5时输出m-总的菜价。
代码:
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int price;
}p[1005];
bool cmp(node a,node b)
{
return a.price>b.price;
}
int main()
{
int n;
int dp[1005];
int m;
while(scanf("%d",&n) && n!=0)
{
memset(dp,0,sizeof(dp));
int sum=0;
int max=0;
int r;
for(int i=0;i<n;i++)
{
scanf("%d",&p[i].price);
sum=sum+p[i].price;
if(max<p[i].price)
{
max=p[i].price;
r=i;
}
}
scanf("%d",&m);
if(sum<=m-5)
{
printf("%d\n",m-sum);
continue;
}
if(m<5)
{
printf("%d\n",m);
continue;
}
for(int i=0;i<n;i++)
for(int j=m;j-p[i].price>=0;j--)
if(dp[j]<dp[j-p[i].price]+p[i].price && r!=i)
{
dp[j]=dp[j-p[i].price]+p[i].price;
}
printf("%d\n",m-dp[m-5]-max);
}
return 0;
}