AcWing 318. 划分大理石 多重背包三

Posted qingyuyyyyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 318. 划分大理石 多重背包三相关的知识,希望对你有一定的参考价值。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5;
int f[N];
int g[N];
int q[N];
int s1[7];
int m;
//数量为a[1...6]
//还是数量

//价值1~6
//变为体积

//然后价值都是1

//问能不能凑出体积为一半
int main() {
    while(cin>>s1[1]>>s1[2]>>s1[3]>>s1[4]>>s1[5]>>s1[6]) {
        m=0;
        for(int i=1; i<=6; i++)
            m+=i*s1[i];
        if(m==0)
            break;
        if(m&1)
            cout<<"Can‘t"<<endl;
        else {
            m>>=1;
            for (int i = 1; i <= 6; i ++ ) {
                int v=1,w=1,s=s1[i];
                memcpy(g, f, sizeof f);//存储上一层,因为会用到上一层的数数据
                for (int j = 0; j < v; j ++ ) {//余数
                    int hh = 0, tt = -1;//滑动窗口,队列
                    for (int k = j; k <= m; k += v) { //表示每一个体积
                        if (hh <= tt && q[hh] < k - s * v)//当队列不空,而且已经滑出窗口
                            hh ++ ;
                        if (hh <= tt)//如果队列不空,更新当且最大值
                            //最大值位队头元素
                            //q[hh]对应最大值对应下标,基础值再加上收益
                            //收益是指里面装了多少个第i个物品,多少个:k-q[hh]/v个,再乘价值
                            //中间空余了多少个第i个物品的体积    空余一个,就可以多放一个物品进来
                            f[k] = max(f[k], g[q[hh]] + (k - q[hh]) / v * w);
                        //弹出没有用的元素       下标减去初始余数
                        //当队列不空,而且队尾价值小于当前价值,队尾就没有意义,弹出
                        while (hh <= tt && g[q[tt]] - (q[tt] - j) / v * w <= g[k] - (k - j) / v * w)
                            tt -- ;
                        q[ ++ tt] = k;//存每个体积
                    }
                }
            }
            if(f[m]==0)
                cout<<"Can‘t"<<endl;
            else
                cout<<"Can"<<endl;
        }
    }
    return 0;
}

以上是关于AcWing 318. 划分大理石 多重背包三的主要内容,如果未能解决你的问题,请参考以下文章

多重背包+二进制拆分 POJ1014

AcWing 4. 多重背包问题(多重背包 朴素版)

ACwing(基础)--- 01背包和完全背包多重背包问题

AcWing 5. 多重背包问题 II

AcWing 5. 多重背包问题 II(二进制优化)

动态规划背包问题总结:01完全多重与其二进制优化分组背包 题解与模板