【NOI P模拟赛】奶油蛋糕塔(状压 DP)
题面

数据范围
1
≤
n
≤
5
×
1
0
5
1\leq n\leq5\times10^5
1≤n≤5×105 。
题解
n
≤
20
n\leq 20
n≤20 的状压应该都会吧,状态记录已经选了的蛋糕集合,以及蛋糕序列的尾部奶油,然后枚举蛋糕转移。
总共有
10
10
10 种不同的蛋糕,数据很小。
把最后的蛋糕塔等效为一个序列,如果有连续三个同种蛋糕,美味度分别为
A
,
B
,
C
A,B,C
A,B,C,那么就可以把他们等效为一个美味度为
A
+
B
+
C
A+B+C
A+B+C 的同种蛋糕,放在原来的位置。于是连续的一段奇数个同种蛋糕都可以合并成一个蛋糕。
现在我们证明一个结论:存在最优解,满足对于每种蛋糕,按上述方式合并后,蛋糕数量不超过 2 个(至多两段连续奇数段)。
考虑用调整法,对于任意解中的任意一种蛋糕,合并后仍存在三个不同位置的蛋糕
a
,
b
,
c
a,b,c
a,b,c ,已知每种蛋糕都有两种方向,由鸽笼原理可得,这三块蛋糕一定至少有两块蛋糕是同向的。不妨设
a
,
b
a,b
a,b 的奶油都是 左
X
X
X 右
Y
Y
Y ,
a
<
b
a<b
a<b ,那么区间
[
a
+
1
,
b
−
1
]
[a+1,b-1]
[a+1,b−1] 的整体就是左
Y
Y
Y 右
X
X
X 。我们把
[
a
+
1
,
b
−
1
]
[a+1,b-1]
[a+1,b−1] 对称翻转,然后移开
a
,
b
a,b
a,b ,把
a
,
b
a,b
a,b 拼起来塞到
c
c
c 的一侧,最后合并
a
,
b
,
c
a,b,c
a,b,c 。整个过程结束,蛋糕序列美味度总和不变,仍然合法,
a
,
b
,
c
a,b,c
a,b,c 却变成了一块蛋糕。
既然合并后每种蛋糕可以不超过两个,那么我们就可以提前把每种蛋糕最大的前奇数个合并到一起,最多留下一个最小的,这样每种蛋糕一开始就只有两个,总的蛋糕数量
n
n
n 降至
20
20
20 ,
就可以用状压了。
CODE
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<random>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 500005
#define LL long long
#define ULL unsigned long long
#define DB double
#define lowbit(x) (-(x) & (x))
#define ENDL putchar('\n')
#define FI first
#define SE second
LL read() {
LL f=1,x=0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<3) + (x<<1) + (s^48); s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar('0'+(x%10));}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) {putchar('-');x = -x;}
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
int n,m,s,o,k;
const int id[4][4] = {{0,1,2,3},{1,4,5,6},{2,5,7,8},{3,6,8,9}};
priority_queue<LL> q[15];
int a[25];
LL w[25];
vector<int> bu[15];
int le[15];
LL dp[1<<20|5][4];
int main() {
freopen("cake.in","r",stdin);
freopen("cake.out","w",stdout);
n = read();
for(int i = 1;i <= n;i ++) {
k = read();
char A = ' ',B = ' ';
while(A == ' ') A = getchar();
while(B == ' ') B = getchar();
int bl = id[A-'W'][B-'W'];
q[bl].push(k);
}
for(int i = 0;i < 10;i ++) {
while((int)q[i].size() > 2) {
LL A = q[i].top();q[i].pop();
LL B = q[i].top();q[i].pop();
LL C = q[i].top();q[i].pop();
q[i].push(A+B+C);
}
while(!q[i].empty()) {
a[m] = i; w[m] = q[i].top(); q[i].pop();
bu[i].push_back(m); le[i] ++;
m ++;
}
}
int tp = (1<<m);
LL ans = 0;
for(int i = 1;i < tp;i ++) {
for(int j = 0;j < 4;j ++) {
for(int k = 0;k < 4;k ++) {
for(int s = 0;s < le[id[k][j]];s ++) {
int x = bu[id[k][j]][s];
if(i & (1<<x))
dp[i][j] = max(dp[i][j],dp[i-(1<<x)][k] + w[x]);
}
}
ans = max(ans,dp[i][j]);
}
}
AIput(ans,'\n');
return 0;
}
【NOI P模拟赛】奶油蛋糕塔(状压 DP)的更多相关文章
- 6.28 NOI模拟赛 好题 状压dp 随机化
算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...
- BZOJ 3812 主旋律 (状压DP+容斥) + NOIP模拟赛 巨神兵(obelisk)(状压DP)
这道题跟另一道题很像,先看看那道题吧 巨神兵(obelisk) 题面 欧贝利斯克的巨神兵很喜欢有向图,有一天他找到了一张nnn个点mmm条边的有向图.欧贝利斯克认为一个没有环的有向图是优美的,请问这张 ...
- 2018.10.05 NOIP模拟 上升序列(状压dp)
传送门 状压dp好题. 首先需要回忆O(nlogn)O(nlog n)O(nlogn)求lislislis的方法,我们会维护一个单调递增的ddd数组. 可以设计状态f(s1,s2)f(s1,s2)f( ...
- 2018.10.01 NOIP模拟 偷书(状压dp)
传送门 状压dp经典题. 令f[i][j]f[i][j]f[i][j]表示到第i个,第i−k+1i-k+1i−k+1~iii个物品的状态是j时的最大总和. 然后简单维护一下转移就行了. 由于想皮一下果 ...
- 旅游(CSUST省赛选拔赛2+状压dp+最短路)
题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...
- [欢乐赛]班服 状压DP
班服 (shirt.pas/.c/.cpp) 时间限制:1s:内存限制 128MB 题目描述: 要开运动会了,神犇学校的n个班级要选班服,班服共有100种样式,编号1~100.现在每个班都挑出了一些样 ...
- [CSP-S模拟测试]:装饰(状压DP)
题目传送门(内部题114) 输入格式 第一行一个正整数$n$. 接下来一行$n-1$个正整数,第$i$个数为$f_{i+1}$. 接下来一行$n$个数,若第$i$个数为$0$则表示林先森希望$i$号点 ...
- war2 洛谷模拟赛day2 t3 状压
(new ) war2 题解:总体数据而言,我们很容易想到着就是DP啊,我们DP数组,用状态压缩,代表有那些点已经被占领过了,代表上一次我占的是那个.对于每一次状态转移,若当前我们要占领的Port ...
- [CSP-S模拟测试]:巨神兵(状压DP)
题目描述 欧贝利斯克的巨神兵很喜欢有向图,有一天他找到了一张$n$个点$m$条边的有向图.欧贝利斯克认为一个没有环的有向图是优美的,请问这张图有多少个子图(即选定一个边集)是优美的?答案对$1,000 ...
- 【CSP模拟赛】Adore(状压dp 二进制)
题目描述 小w偶然间见到了一个DAG.这个DAG有m层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有k个节点.现在小w每次可以取反第i(1<i<n-1)层和第i+1层之间的连 ...
随机推荐
- Dcoker镜像管理与容器应用
Dcoker镜像管理与容器应用 docker基于镜像创建容器 相同版本的镜像只允许存在一个 同一个镜像可以创建多个容器 镜像管理 [root@localhost ~]# docker pull cen ...
- C#实现[移除文件名中的非中文字符]
更新记录: 2022年5月28日 从程序中抽出方法复用. 处理财务文件时写的一个小函数.用于移除文件名中的非中文字符. /// <summary> /// 移除文件名中的非中文字符 /// ...
- php类精确验证身份证号码
<?php // check class check{ // $num为身份证号码,$checkSex:1为男,2为女,不输入为不验证 public function checkIdentity ...
- 接口偶尔超时,竟又是JVM停顿的锅!
原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 继上次我们JVM停顿十几秒的问题解决后,我们系统终于稳定了,再也不会无故重启了! 这是之前的文章:耗时几个月,终于 ...
- Spring Security认证器实现
目录 拦截请求 验证过程 返回完整的Authentication 收尾工作 结论 一些权限框架一般都包含认证器和决策器,前者处理登陆验证,后者处理访问资源的控制 Spring Security的登陆请 ...
- Linux IO重定向和管道
计算机组成部分: 由io . 控制器.计算器.存储器组成 IO: input output 计算机里面通过终端窗口实现输入和输出,键盘鼠标屏幕这些只是手段,真正完成输入输出的是终端窗口 标准输入.出. ...
- 如何通过WinDbg获取方法参数值
引入 我们在调试的过程中,经常会通过查看方法的输入与输出来确定这个方法是否异常.那么我们要怎么通过 WinDbg 来获取方法的参数值呢? WinDbg 中主要包含三种命令:标准命令.元命令(以 . 开 ...
- UML图记忆技巧
什么是UML类图 Class Diagram:用于表示类.接口.实例等之间相互的静态关系 虽然名字叫类图,但类图中并不只有类 记忆技巧 UML箭头方向: 从子类指向父类 我相信 很多同学都会有和我一样 ...
- 2005/2010/2015-2021年全国兴趣点POI数据
数据下载链接:数据下载链接 POI是"Point of Interest"的缩写,中文可以翻译为"兴趣点".POI数据会包含各种信息,如前面提到的名称.别名等信 ...
- poste.io自建邮件服务器
随便说些什么 腾讯企业邮新增账号不方便,这里的主要是指不经过手机验证或微信扫码的,虽然提供了最多3个"业务邮箱",很明显不够用. EwoMail,装没装起来我不记得了,反正是不好用 ...