分析:
首先要声明,题目有一些描述不准确的地方:
- 背包一定要恰好装满
- 不剔除相同数值的解
这是一道01背包K优解的问题
唯一的不同就是:背包必须装满
实际上这个问题也非常好解决:
如果我们不要求装满,取的是最大值,那么f的初始值就是0
如果要求装满,那么f的初始值就是-INF,其中f[0]=0
怎么理解呢:
初始化的f数组实际上就是在没有任何物品可以放入背包时的合法状态。
如果要求背包恰好装满,那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,
其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。
如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,
这个解的价值为0,所以初始时状态的值也就全部为 0了
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int f[5005][55],a[55],b[55];
int w[203],v[203];
int n,m,K;
int main()
{
scanf("%d%d%d",&K,&m,&n);
for (int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
memset(f,128,sizeof(f)); //注意初始化
int i,j,p;
f[0][1]=0; //注意初始化
for (i=1;i<=n;i++)
{
for (j=m;j>=w[i];j--)
{
for (p=1;p<=K;p++)
{
a[p]=f[j][p];
b[p]=f[j-w[i]][p]+v[i];
}
a[K+1]=b[K+1]=-1;
int x,y,z;
x=y=z=1;
while (z<=K&&(a[x]!=-1||b[y]!=-1))
{
if (a[x]>b[y])
f[j][z]=a[x],x++;
else f[j][z]=b[y],y++;
z++; //不剔除重复解
}
}
}
int ans=0;
for (int i=1;i<=K;i++) ans+=f[m][i];
printf("%d\n",ans);
return 0;
}