BAN-Bank Notes(更麻烦的背包方案)

传送门

这题的记录方案,真是,毒瘤........

\(很明显的二进制优化多重背包\)

\(重点是,如何记录方案?\)

\(用一维的pre数组是不行的!!(不信你去试试,方案之间选的物品会重复)\)

\(那就用二维的pre[i][j],等于1代表选了i物品,等于0相当于没选\)

最后记得设置成bool类型。

#include <bits/stdc++.h>
using namespace std;
const int maxn=3000;
int n,m;
struct p{
	int v,w,h;
}a[3009];
int cnt,q[309],dp[20009],h[20009];
bool pre[3009][20009];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>q[i];
	for(int i=1;i<=n;i++)	
	{
		int s;
		cin>>s;
		for(int j=1;j<=s;j*=2)
		{
			s-=j;
			a[++cnt].v=j*q[i],a[cnt].w=j,a[cnt].h=i;
		}
		if(s!=0)
			a[++cnt].v=s*q[i],a[cnt].w=s,a[cnt].h=i;
	}
	cin>>m;
	memset(dp,20,sizeof(dp));
	dp[0]=0;
	for(int i=1;i<=cnt;i++)
	for(int j=m;j>=a[i].v;j--)
	{
		if(dp[j]>dp[j-a[i].v]+a[i].w)
		{
			pre[i][j]=1;
			dp[j]=dp[j-a[i].v]+a[i].w;	
		}	
	}
	int ji=cnt,z=m;
	while(1)
	{
		if(pre[ji][z])//如果选了ji这个物品,开始转移 
		{
			z-=a[ji].v;
			h[a[ji].h]+=a[ji].w;
		}
		ji--;
		if(ji==0)	break;
	}
	cout<<dp[m]<<endl;
	for(int i=1;i<=n;i++)	cout<<h[i]<<" ";
}
posted @ 2020-04-13 12:53  倾叶子佮  阅读(148)  评论(0编辑  收藏  举报