关于多重背包理解的一点思考和拨乱反正

题目如下:
对于每一组样例,给你六种玻璃球,每种有着不同的价值,现在问你,你能否在不拆分同一颗玻璃球价值的同时分成价值相同的两份?


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int n1=0,a[120001],cost[101],value[101],sum=0,num[7];
int main()
{
    int time=0;
    while(1)
    {
        sum=0;
        n1=0;
        for(int i=1;i<=6;i++)
        {
            scanf("%d",num+i);
            sum+=num[i]*i;
        }
        if(sum==0) break;
        if(sum%2==1){
            printf("Collection #%d:\n",++time);
            printf("Can't be divided.\n\n");
            continue;
        }
        memset(a,0,sizeof(a));
        for(int i=1;i<=6;i++)
        {
            int s=num[i],t=1;
            while(s>=t)
            {
                if(t*i)
                {
                    cost[++n1]=t*i;
                value[n1]=t*i;
                }

                s-=t;
                t*=2;
            }
            if(s*i){
                cost[++n1]=s*i;
            value[n1]=s*i;
            }

        }
        for(int i=1;i<=n1;i++)
        {
            for(int j=sum/2;j>=cost[i];j--)
            {
                a[j]=max(a[j],a[j-cost[i]]+value[i]);
            }
        }
        if(sum/2==a[sum/2]) {printf("Collection #%d:\n",++time);printf("Can be divided.\n\n");}
        else {printf("Collection #%d:\n",++time);
            printf("Can't be divided.\n\n");}
    }

}

1.对于多重背包,首先要进行二进制优化。如果是0颗该种玻璃球,则直接忽略过去。(代码中的if(ti),if(si));
2.对于广泛的背包问题,如维护了一个a[1000]的数组,那么下标为x,就严格地代表x这个容量下最多可以容纳最多a【x】价值的东西。
之前的错误理解在于,譬如说01背包的逆序,是盲目的进行“拿不拿”的判断,而之前的状态不论存在与否。这是错误的。当维护出来a【x】时,哪怕a【x-cost【i】】不涉及该状态,那么其也应该不小于第x变量前面“设计状态”的价值。
举个例子。
我现在有重量和价值分别为1,5,6的玻璃球。
我要维护一个背包数组。
先考虑价值为6的玻璃球,维护后:
0 0 0 0 0 6 6 6 6 6 6 6
再考虑价值为5的玻璃球
0 0 0 0 5 6 6 6 6 6 11 11
再考虑价值为1的玻璃球
0 1 1 1 5 6 7 7 7 7 11 12
你品 你细品。
3.定义:
若使得价值==重量,进而
若维护出来一个背包数组a【13】,若对于下标为x的变量a【x】,如果在x这个容量下,塞下物品的重量恰好是x,则称为“真装填”,否则称之为“假装填”。
举个例子。我要装填重量分别为2,4,5的三件物品。则容量为11的背包能够容纳,则a【11】为真装填。但是如果给你一个a【12】的背包,多出的一个容量啥用没有,只能顺承容量为11时背包的数据,则这就是假装填。
这个原理可以应用于判断物品装载可不可能恰好到达一个容量v(真装填)。
这一道题就是这样。如果判断出sum/2= =a[sum/2],则认定为在sum/2容量下能够真装填,则可以分开。
也可以这样理解:等于重量的value是“背包实际装载量”,而下标x的容量为“最大装载量”,当且仅当背包实际装载量等于最大装载量时,是真装载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值