给你n个物品,还有一个容量为v的容器,随后在给你n个物品的重量c和价值w
F[i][j]表示把前i个物品放在容量为j的背包的最大价值
然后根据第i件物品是否要放来决策
F[i-1][j]表示前i-1个物品放在容量为j的背包中的最大价值
F[i-1][j-C[i]]+W[i]表示若是要放第i件物品 那么前i-1个物品所要用的背包容量为j-C[i]
然后取两者的最大值即可
二维的做法:
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= v; j++)
{
F[i][j] = (i==1?0:F{i-1}[j]);
if(j >= C[i])
F[i][j] = max(F[i][j],F[i-1][j-C[i]]+W[i]);
}
}
一维的方法
for(int i = 1; i <= n; i++)
{
for(int j = v; j >= C[i]; j--)
{
F[j] = max(F[j],F[j-C[i]]+W[i]);
}
}
当然一维要比二维的空间复杂度小
一些浅显的认识,欢迎提意见
那么接下来就看看实际问题吧
hdu 2564 饭卡
如果输入的m大于5 那么要用5元去买最贵的菜 然后在剩余的菜 进行01背包的算法就可以了
AC代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
int pr[3000],dp[3000];
int max(int x,int y)
{
if(x < y)
return y;
else
return x;
}
int main()
{
int max1,n,m;
while(cin >> n,n)
{
memset(dp,0,sizeof(dp));
memset(pr,0,sizeof(pr));
for(int i = 1; i <= n; i++)
scanf("%d",&pr[i]);
sort(pr + 1, pr + 1 + n);
max1 = pr[n];
scanf("%d",&m);
if(m<5)
{
printf("%d\n",m);
continue;
}
m-=5; ///保留5元 买最贵的
for(int i = 1; i < n; i++)
{
for(int j = m; j >= pr[i]; j--)
{
dp[j] = max(dp[j],dp[j-pr[i]]+pr[i]);
}
}
printf("%d\n",m+5-max1-dp[m]);
}
return 0;
}