Example:hdu 2546:http://acm.hdu.edu.cn/showproblem.php?pid=2546
解:利用“01背包”状态方程:F[v] = max(F[v], F[v-ci]+wi)
(1)对这个问题来说,干扰项是最后的5元,可以买任何一道菜,所以可以先用5元买最贵的一道菜(反正买最后一道菜时至少要有5元余额,不如先不考虑这5元);去掉干扰项后就是一个“01”问题了。
(2)一道菜 i 的价格menu[i],既是“背包体积”,又是“背包价值”。
(3)最优子结构:value[i],表示“i元买菜,可以最多花几元”。
/*
*
* 01背包问题变形
* 目标是找余额最少的情况,也就是花最多的情况
*/
#include <iostream>
#include <algorithm>
using namespace std;
int Item[1002];
int Value[1010]; // Value[i]表示i元最多可以花多少
template<class T>
T max(const T &a, const T &b)
{
return a>b?a:b;
}
int main()
{
int n,W;
while((cin>>n) && n)
{
memset(Item, 0, sizeof(Item));
for(int i=1; i<=n; i++)
cin >> Item[i]; // 价格(背包体积)
sort(Item+1, Item+n+1);
int maxItem = Item[n]; // 把最大的一个菜买到
cin >> W; // 余额(背包容量)
for(int j=1; j<n; j++) // 每种物品或买或不买
{
for(int k=W; k>=Item[j]; k--)
Value[k] = max(Value[k], Value[k-Item[j]]+Item[j]);
}
cout << (W-Value[W-5]) - maxItem << endl;
}
return 0;
}