一、题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2546
我认为01背包就是——对n个物品进行取舍,在一定的限制条件下如何取得最优解的一类问题。
此题和再学01背包(一) 中的标准01背包的比较。
标准01背包 | 本题 | |
花费(或者代价) | cost[i] | cost[i] |
价值(或者贡献) | val[i] | -cost[i] |
限制条件 | if(cost[i]<=v) 可放 | if( v>=5) 可买 |
最优解 | 贡献最大 | 贡献最小(即绝对值最大) |
错误写法:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define FOR(i,k,n) for(int i=k;i<n;i++)
#define FORR(i,k,n) for(int i=k;i<=n;i++)
#define scan(a) scanf("%d",&a)
#define scann(a,b) scanf("%d%d",&a,&b)
#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mst(a,n) memset(a,n,sizeof(a))
#define ll long long
#define N 1005
#define mod 1000000007
#define INF 0x3f3f3f3f
const double eps=1e-8;
const double pi=acos(-1.0);
int cost[N];
int dp[N][N];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,v;
while(cin>>n)
{
if(n==0) break;
mst(dp,0);
for(int i=1;i<=n;i++)
cin>>cost[i];
cin>>v;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=v;j++)
{
if(j>=5) dp[i][j]=max(dp[i-1][j-cost[i]<0?0:j-cost[i]]+cost[i],dp[i-1][j]);
else dp[i][j]=0;
}
}
cout<<v-dp[n][v]<<endl;
}
return 0;
}
错误原因:没有考虑到本题限制条件的特殊性——在用饭卡买最后一个菜的时候,可以使用一次特权,以小博大,只要有5块,不管多贵都能买。这里就体现出了本题的限制条件隐含着贪心的性质。
正确代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define FOR(i,k,n) for(int i=k;i<n;i++)
#define FORR(i,k,n) for(int i=k;i<=n;i++)
#define scan(a) scanf("%d",&a)
#define scann(a,b) scanf("%d%d",&a,&b)
#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mst(a,n) memset(a,n,sizeof(a))
#define ll long long
#define N 1005
#define mod 1000000007
#define INF 0x3f3f3f3f
const double eps=1e-8;
const double pi=acos(-1.0);
int cost[N];
int dp[N][N];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,v;
while(cin>>n)
{
if(n==0) break;
mst(dp,0);
for(int i=1;i<=n;i++)
cin>>cost[i];
sort(cost+1,cost+n+1);
cin>>v;
if(v>=5)
{
for(int i=1;i<n;i++)
{
for(int j=0;j<=v-5;j++)
{
if(j>=cost[i]) dp[i][j]=max(dp[i-1][j-cost[i]]+cost[i],dp[i-1][j]);
else dp[i][j]=dp[i-1][j];
}
}
cout<<v-dp[n-1][v-5]-cost[n]<<endl;
}
else cout<<v<<endl;
}
return 0;
}