P1858 多人背包(01背包的前k优解和)

传送门

\(背包其实万变不离其宗\)

\(普通的转移时(v表示体积w表示价值)\)

\[dp[i]=max(dp[i],dp[i-v]+w) \]

\(现在情况稍微有点不同,我们需要保留dp[i]的前k优解,同样也保留了dp[i-v]的前k优解\)

\(可以这样简单的表示\)

\(其实总共可以从dp[i]的前k优解和dp[i-v]的前k优解转移过来,也就是从k+k中状态选前k优解转移\)

\(怎么实现的可以看代码\)

#include <bits/stdc++.h>
using namespace std;
int f[5009][60],ans=0;
int k,v,n,vv[209],value[209];
int main()
{
	for(int i=0;i<=5000;i++)
	for(int j=0;j<=60;j++)	f[i][j]=-999999999;
	scanf("%d%d%d",&k,&v,&n);
	for(int i=1;i<=n;i++)	cin>>vv[i]>>value[i];//体积和价值 
	f[0][1]=0;
	for(int i=1;i<=n;i++)
	for(int j=v;j>=vv[i];j--)
	{
		int t1=1,t2=1,t[60],len=0;
		while(t1+t2<=k+1)
		{
			if(f[j][t1]>f[j-vv[i]][t2]+value[i])
				t[++len]=f[j][t1++];//选一种大的转移 
			else
				t[++len]=f[j-vv[i]][t2++]+value[i];
		}
		for(int K=1;K<=k;K++)	f[j][K]=t[K];
	}
	for(int i=1;i<=k;i++)	ans+=f[v][i];
	cout<<ans;
}
posted @ 2020-05-12 16:00  倾叶子佮  阅读(117)  评论(0编辑  收藏  举报