http://acm.hdu.edu.cn/showproblem.php?pid=2546
分析:现要求你买过东西后卡上余额最少,而卡上余额只要大于等于5,那么一定可以购买成功,那么我们直接想法是要用这5元去买最贵的东西,(但是当卡上余额不足5元时,那么此时余额就是最小值了)。我们可以让余额先减去5,然后用剩下的钱进行背包,看最多还可以消费多少钱。状态方程为:dp[j]=max(dp[j], dp[j-a[i]]+a[i]),dp[j]表示的是买前i件商品,预算为j时的最大花销。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; typedef long long LL; #define maxn 1100 int dp[maxn], a[maxn]; int main() { int n, sum; while(scanf("%d", &n), n) { for(int i=0; i<n; i++) scanf("%d", &a[i]); scanf("%d", &sum); if(sum<5) { printf("%d\n", sum); continue; } sum -= 5; sort(a, a+n); memset(dp, 0, sizeof(dp)); for(int i=0; i<n-1; i++) { for(int j=sum; j>=a[i]; j--) { dp[j] = max(dp[j-a[i]]+a[i], dp[j]); } } printf("%d\n", sum+5-dp[sum]-a[n-1]); } return 0; }