背景:1——WA:卡上最低要求为5元才能消费的边界情况没有处理。
思路:首先判断卡上余额是否有五元,不是直接输出。然后,从卡里面拿出五元来买最大价值,剩下的钱尽可能用完就可以了。
学习:1.这里透露了一个基本问题:从n个数中选取m个数,使这m个数的和尽可能的接近k。这个体是把k看做背包的容量,把一个数的值既看做价值又看做体积,转化为01背包问题。
我的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int value[1009],F[1001];
int sum(int i,int n){
int ok=0;
for(;i < n;i++) ok+=value[i];
return ok;
}
int main(void){
int n,money,max_price=0,mp;
while(~scanf("%d",&n),n){<span id="transmark"></span>
max_price=0;
for(int i=0;i < n;i++){
scanf("%d",&value[i]);
if(value[i] > max_price){
mp=i;
max_price=value[i];
}
}
value[mp]=0; // 最大单价的隔离出来
scanf("%d",&money);
if (money-5 >= 0) money-=5; //卡上要保留5元钱,最低消费额为5元
else{
printf("%d\n",money);
continue;
}
memset(F,0,sizeof(F));
for(int i=0;i < n;i++){
int min=max(value[i],money-sum(i,n)); //总价值减去,后面所有物品的总价值,一个常数的优化
for(int j=money;j >= min;j--) //注意这里是大于等于
F[j]=max(F[j],F[j-value[i]]+value[i]); //注意这里是当前背包容量j减去花费容量
}
printf("%d\n",money+5-F[money]-max_price);
}
return 0;
}