http://acm.hdu.edu.cn/showproblem.php?pid=2546
这仍然是一个 0-1背包 的问题 和上一题 2602 类似。思路是:在饭卡的余额大于等于5时 我们可以买下任意价值的菜 所以我们只需要 在饭卡的余额小于五之前买下价值尽可能多的菜 然后 再买下价值最大的菜即可
AC代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int cmp(const void *a,const void *b){
return *(int *)a-*(int *)b;
}
int max(int a,int b){
return a>b?a:b;
}
int dp[1005][1005];
int main (){
int n;
int v;
int num[1005];
while (scanf("%d",&n)&&n)
{
for (int i=1;i<=n;i++)
scanf ("%d",&num[i]);
scanf ("%d",&v);//饭卡的金额
memset(dp,0,sizeof(dp));
if (v<5)//如果饭卡的金额小于5 不能买
printf ("%d\n",v);
else//大于等于5可以买
{
qsort(num+1,n,sizeof(num[0]),cmp); //升序排列 留下最大的一个
// 找出在 v-5 的余额下能买到的菜的最大价值
for (int i=1;i<n;i++)
{
for (int j=0;j<=v-5;j++)// v-5 表示给饭卡留下五块钱来买价值最大的菜
{
if (num[i]<=j)
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-num[i]]+num[i]);// 状态转移方程 用来判断选取 是否牺牲余额买下该物体
}
else{
dp[i][j]=dp[i-1][j];
}
}
}
printf ("%d\n",v-dp[n-1][v-5]-num[n]);
}
}
return 0;
}