给定N种物品和一个容量为M的背包,每种物品都有三个属性:价值 wi 、体积 vi 、个数 ci
目标:选择若干个物品装入背包,使其容量和不超过M,并最大化价值和
设 fi,j 表示考虑前 i 种物品,装入容量为 j 的背包获得的最大价值
状态转移方程如下:
观察方程
hdu 2191,不加优化就能过
CodeVS 5429,必须用单调队列优化(题目卡log)
这是hdu2191
//多重背包 单调队列优化
#include
#include
#include
#define maxn 1100
#define maxm 1100
using namespace std;
int N, M, p[maxn], h[maxn], c[maxn], qw[maxm], qn[maxm], f[maxn][maxm];
void input()
{
int i, j;
scanf("%d%d",&M,&N);
for(i=1;i<=N;i++)scanf("%d%d%d",p+i,h+i,c+i);
}
void dp(int *f, int *g, int prize, int height, int c)
{
int l=1, r=1, d=0, k, a, b, mini;
for(b=0;b
{
l=1,r=1,qw[r]=g[b],qn[r++]=b;
for(a=0,d=0;a+b<=M;a+=prize,d+=height)
{
while(qw[r-1]+d<=g[a+b] and l
qw[r]=g[a+b]-d,qn[r++]=a+b;
mini=max(0,a+b-prize*c);
while(qn[l]
f[a+b]=qw[l]+d;
}
}
}
int main()
{
int C, i, j;
scanf("%d",&C);
while(C--)
{
input();
for(i=1;i<=N;i++)dp(f[i],f[i-1],p[i],h[i],c[i]);
printf("%d\n",f[N][M]);
}
return 0;
}
这是CodeVS 5429
#include
#include
#include
#define maxn 7010
#define maxm 7010
using namespace std;
int N, M, p[maxn], h[maxn], c[maxn], qw[maxm], qn[maxm], f[2][maxm];
void input()
{
int i, j;
scanf("%d%d",&N,&M);
for(i=1;i<=N;i++)scanf("%d%d%d",p+i,h+i,c+i);
}
void dp(int *f, int *g, int prize, int height, int c)
{
int l=1, r=1, d=0, k, a, b, mini;
for(b=0;b
{
l=1,r=1,qw[r]=g[b],qn[r++]=b;
for(a=0,d=0;a+b<=M;a+=prize,d+=height)
{
while(qw[r-1]+d<=g[a+b] and l
qw[r]=g[a+b]-d,qn[r++]=a+b;
mini=max(0,a+b-prize*c);
while(qn[l]
f[a+b]=qw[l]+d;
}
}
}
int main()
{
int i, j;
input();
for(i=1;i<=N;i++)dp(f[i&1],f[~i&1],p[i],h[i],c[i]);
printf("%d\n",f[N&1][M]);
return 0;
}