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. 划分大理石 多重背包三的主要内容,如果未能解决你的问题,请参考以下文章