题目:
题解:
这个题目每一种最优解是要求背包装满的
Q1:如何解决必须装满的背包
A1:只需要将初始的f数组全变成负的,只有f[0]初始值为0,就可以保证装满,这样做的原因是f“顺便”表示为这个状态是否能达到(满)
Q2:如何找到前k优解
A2:多开一维表示为第k优解,每次用归并的方法记录前k+1优解(归并f[j][k]和f[j-w[i]][k]+v[i])
代码:
#include <cstdio>
#include <cstring>
using namespace std;
int p,V,n,i,j,k,v[205],w[205],t[55],a[55],b[55];
int f[5005][50;//这里要加右括号我就没有高亮代码...
int main()
{
scanf("%d%d%d",&p,&V,&n);
for (i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
memset(f,0x8f,sizeof(f));
f[0][1]=0;
for (i=1;i<=n;i++)
for (j=V;j>=w[i];j--)
{
int len=0,t1=1,t2=1;
for (k=1;k<=p;k++)
a[k]=f[j][k],b[k]=f[j-w[i]][k]+v[i];
a[p+1]=b[p+1]=-1;
while (len<=p+1 && (a[t1]!=-1 || b[t1]!=-1))
{
if (a[t1]<b[t2]) f[j][++len]=b[t2++];
else f[j][++len]=a[t1++];
// if (f[j][len]==f[j][len-1]) len--;
}
}
int ans=0;
for (i=1;i<=p;i++) ans+=f[V][i];
printf("%d",ans);
}