• 多重背包及其优化


    (1)二进制的优化

    这是一个多重背包的模板,也是十分好用的一种模板,因为这个比直接拆除01 背包来做

    要省些时间。这是为啥呢,首先先由我讲一下为什么能换成01 背包吧。

    举个例子。假如给了我们 价值为 2,但是数量却是10 的物品,我们应该把10给拆开,要知道二进制可是能够表示任何数的,所以10 就是可以有1,2, 4,8之内的数把它组成,一开始我们选上 1了,然后让10-1=9,再选上2,9-2=7,在选上 4,7-4=3,

    而这时的3<8了,所以我们就是可以得出 10由 1,2,4,3,来组成,就是这个数量为1,2,3,4的物品了,那么他们的价值是什么呢,是2,4,6,8,也就说给我们的价值为2,数量是10的这批货物,已经转化成了价值分别是2,4,6,8元的货物了,每种只有一件哎!!!!这就是二进制优化的思想。

    那为什么会有完全背包和01 背包的不同使用加判断呢?原因也很简单啊,当数据很大,大于背包的容纳量时,我们就是在这个物品中取上几件就是了,取得量时不知道的,也就理解为无限的啦,这就是完全背包啦,反而小于容纳量的就是转化为01背包来处理就是了,可以大量的省时间。

    AC代码:

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define N 1000         //物品个数 
    #define M 100000000    //所有物品可能的最大价值 
    int m[N],c[N],w[N],f[M];
    int V;
    int max(int a,int b){return a>b?a:b;}
    void ZeroOnePack(int cost,int weight)
    {
        int v;
        for(v=V;v>=cost;v--) f[v]=max(f[v],f[v-cost]+weight);
    }
    void CompletePack(int cost,int weight)
    {
        int v;
        for(v=cost;v<=V;v++)
            f[v]=max(f[v],f[v-cost]+weight);
    }
    void MultiplePack(int cost,int weight,int amount)
    {
        int k;
        if(cost*amount>=V)
        {
            CompletePack(cost,weight);
            return;
        }
        k=1;
        while(k<amount)
        {
            ZeroOnePack(k*cost,k*weight);
            amount=amount-k;
            k=k*2;
        }
        ZeroOnePack(amount*cost,amount*weight);
    }
    int main()
    {
        int n,i;
        scanf("%d %d",&n,&V);
                                                       // 两种不同的初始化方式,根据情况自行选择 
        //memset(f,0,sizeof(f[0])*(V+1));              // 只希望价格尽量大 
        //memset(f,-M,sizeof(f[0])*(V+1));f[0]=0;      // 要求恰好装满背包 
        for(i=0;i<n;i++) scanf("%d %d %d",m+i,c+i,w+i);
        for(i=0;i<n;i++) MultiplePack(c[i],w[i],m[i]);
        printf("%d
    ",f[V]);
        system("PAUSE");
        return 0;
    }
    View Code

    (2)单调队列优化

    解析

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    #define ll long long
    using namespace std;
    int n,m,he,ta,T;
    ll f[10010],q[10010],num[10010];
    int main()
    {
        int i,j,w,v,s,d;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            for(i=0;i<=m;i++)f[i]=0;
            for(i=1;i<=n;i++){
                scanf("%d%d%d",&w,&v,&s);
                if(s>m/w)s=m/w;
                for(d=0;d<w;d++){
                    he=ta=1;
                    for(j=0;j<=(m-d)/w;j++){//先存进去,后取出来
                        int tmp=f[j*w+d]-v*j;
                        while(he<ta&&q[ta-1]<=tmp)--ta;
                        q[ta]=tmp,num[ta++]=j;
                        while(he<ta&&j-num[he]>s)++he;
                        f[j*w+d]=max(f[j*w+d],q[he]+v*j);
                    }
                }
            }
            printf("%lld
    ",f[m]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    PHP生成pdf文档
    PHP将数据库数据批量生成word文档
    三个常用的PHP图表类库
    Javascript——(1)
    python学习HTML之CSS(2)
    python学习HTML之CSS
    python学习之HTML
    python学习之rabbitmq
    第10周15/16/17
    多进程
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9043143.html
Copyright © 2020-2023  润新知