整体贪心 + 局部01背包 之 hdu 2546

来源:互联网 发布:网络安全设备巡检 编辑:程序博客网 时间:2024/05/24 00:47
//  [7/16/2014 Sjm]/*虽然知道5元是解决关键,但自己没想到将5元单独提出来处理,结果一致wa。。。01背包变形:目标:尽量使卡上的余额最少,也就是说尽可能让花销最大。 分析:购买菜时,只可能出现三种情况 :1)M < 5 :  直接输出 M ;2)饭卡金额M >= 所有菜的价格总和sum: 答案即 M-sum;3)饭卡金额M < 所有菜的价格总和sum :   5元是可以买最贵的菜的最小花费,再尽可能的花去(M-5)元。a.5元直接提出,可以从饭卡金额中减去最贵的菜的价格b.用(M-5)元去买非a中所买的菜, 尽可能的多花:  01背包,使价值和体积看成相等,即在保证容量在(M-5)的范围内,价值取到最大*/
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAX = 1005;int N, M;int val[MAX], dp[MAX];int Solve() {memset(dp, 0, sizeof(dp));for (int i = 1; i < N; ++i) {for (int j = M - 5; j >= val[i]; --j) {dp[j] = max(dp[j], dp[j - val[i]] + val[i]);}}return dp[M - 5];}int main() {//freopen("input.txt", "r", stdin);//freopen("output.txt", "w", stdout);while (~scanf("%d", &N) && N) {int sum = 0;for (int i = 1; i <= N; ++i) {scanf("%d", &val[i]);sum += val[i];}scanf("%d", &M);if (M < 5) {printf("%d\n", M);continue;}if (sum <= M) {printf("%d\n", (M - sum));continue;}sort(val + 1, val + N + 1);int i = 1;printf("%d\n", M - Solve() - val[N]);}return 0;}
0 0