• 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]<<" ";
    }
    
  • 相关阅读:
    北京集训:20180325
    北京集训:20180323
    北京集训:20180321
    北京集训:20180320
    Bzoj5209[Tjoi2012]防御:姿势题
    北京集训:20180318
    北京集训:20180316
    北京集训:20180314
    北京集训:20180313
    Bzoj4818:生成函数 快速幂
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12690695.html
Copyright © 2020-2023  润新知