[省选联考 2020 A/B 卷] 信号传递(状压dp + 卡空间)

problem

luogu-P6622

一条道路上从左至右排列着 mmm 个信号站,初始时从左至右依次编号为 1,2,…,m1,2,\dots,m1,2,,m,相邻信号站之间相隔 111 单位长度。

每个信号站只能往它右侧的任意信号站传输信号(称为普通传递),每单位长度距离需要消耗 111 单位时间。

道路的最左侧有一个控制塔,它在最左侧信号站的左侧,与其相隔 111 单位长度。

控制塔能与任意信号站进行双向信号传递(称为特殊传递),但每单位长度距离需要消耗 kkk 个单位时间。

对于给定的长度为 nnn 的信号传递序列 SSS,传递规则如下:

  1. n−1n-1n1 次信号传递,第 iii 次信号传递将把信号从 SiS_iSi 号信号站传递给 Si+1S_{i+1}Si+1 号。
  2. Si+1S_{i+1}Si+1 号信号站在 SiS_iSi 号右侧,则将使用普通传递方式,从 SiS_iSi 号直接传递给 Si+1S_{i+1}Si+1 号。
  3. Si+1S_{i+1}Si+1号信号站在 SiS_iSi 号左侧,则将使用特殊传递方式,信号将从 SiS_iSi 号传递给控制塔,再由控制塔传递给 Si+1S_{i+1}Si+1 号。
  4. Si=Si+1S_i=S_{i+1}Si=Si+1,则信号无须传递。

阿基作为大工程师,他能够任意多次交换任意两个信号站的位置,即他能够重排信号站的顺序,这样会使得 SSS 消耗的传递时间改变。

现在阿基想知道,在他重排信号站顺序后,SSS 所消耗的传递时间最小能是多少。

solution

假设坐标在 x,yx,yx,y 的两个信号塔之间有一次 x→yx\rightarrow yxy 的传递,可以形式化地表示:
{y−xx≤ykx+kyx>y\begin{cases} y-x&&x\le y\\ kx+ky&&x>y \end{cases} {yxkx+kyxyx>y
这是同构的,也就是说对于每个传递的贡献可以拆成两个信号塔的各自贡献。

假设坐标在 yyy 的信号塔,如果有坐标 x→yx\rightarrow yxy 的传递。

  • 则对于 yyy 所代表的信号塔而言:
    • x≤yx\le yxy,产生 111
    • x>yx>yx>y,产生 kkk
  • 反之同理,对于 xxx 所代表的信号塔而言:
    • x≤yx\le yxy,产生 −1-11
    • x>yx>yx>y,产生 kkk

则最终代价等于每个点的贡献乘以其坐标再求和。

具体的数学形式推导:

cnt(i,j):cnt(i,j):cnt(i,j): 有多少次信号塔 i→ji\rightarrow jij 的传递,即 cnt(i,j)=∑k=1n[Sk=i][Sk+1=j]cnt(i,j)=\sum_{k=1}^n[S_k=i][S_{k+1}=j]cnt(i,j)=k=1n[Sk=i][Sk+1=j]

设下标 ppp 处是 idpid_pidp 号信号站,推导一下每个下标对答案的贡献。
ans=∑i=1m∑j=i+1mcnt(idi,idj)∗(j−i)+∑i=1m∑j=1i−1cnt(idi,idj)∗(i+j)∗kans=\sum_{i=1}^m\sum_{j=i+1}^mcnt(id_i,id_j)*(j-i)+\sum_{i=1}^m\sum_{j=1}^{i-1}cnt(id_i,id_j)*(i+j)*k ans=i=1mj=i+1mcnt(idi,idj)(ji)+i=1mj=1i1cnt(idi,idj)(i+j)k=∑i=1mi(∑j=i+1m(k∗cnt(idj,idi)−cnt(idi,idj))+∑j=1i−1(k∗cnt(idi,idj)+cnt(idj,idi)))=\sum_{i=1}^mi\bigg(\sum_{j=i+1}^m\Big(k*cnt(id_j,id_i)-cnt(id_i,id_j)\Big)+\sum_{j=1}^{i-1}\Big(k*cnt(id_i,id_j)+cnt(id_j,id_i)\Big)\bigg) =i=1mi(j=i+1m(kcnt(idj,idi)cnt(idi,idj))+j=1i1(kcnt(idi,idj)+cnt(idj,idi)))

f(s):f(s):f(s): 考虑到 ∣s∣|s|s 位(∣s∣:s|s|:ss:s 二进制下 111 的个数),前 ∣s∣|s|s 位的信号站编号集合为 sss 时的最小代价。

那么 ∑j=i+1m(k∗cnt(idj,idi)−cnt(idi,idj))+∑j=1i−1(k∗cnt(idi,idj)+cnt(idj,idi))\sum_{j=i+1}^m\Big(k*cnt(id_j,id_i)-cnt(id_i,id_j)\Big)+\sum_{j=1}^{i-1}\Big(k*cnt(id_i,id_j)+cnt(id_j,id_i)\Big)j=i+1m(kcnt(idj,idi)cnt(idi,idj))+j=1i1(kcnt(idi,idj)+cnt(idj,idi)) 形式中的 jjj 其实就是以 ∣s∣|s|s 为划分点,分成在 sss 集合内的编号信号塔和不在的信号塔。

于是我们可以预处理这部分的贡献,只需要知道 iii 和集合 sss 即可。

规范化的,令 g(i,s)=∑j∉s∧j≠ik∗cnt(idj,idi)−cnt(idi,idj)+∑j∈sk∗cnt(idi,idj)+cnt(idj,idi)g(i,s)=\sum_{j\not\in s\wedge j\ne i}k*cnt(id_j,id_i)-cnt(id_i,id_j)+\sum_{j\in s}k*cnt(id_i,id_j)+cnt(id_j,id_i)g(i,s)=jsj=ikcnt(idj,idi)cnt(idi,idj)+jskcnt(idi,idj)+cnt(idj,idi)

先预处理 g(i,0)g(i,0)g(i,0),然后每次枚举 sss 二进制下的一个 111(随便拎个 lowbitlowbitlowbit 位)即可 O(1)O(1)O(1) 转移。

一个数从 ∉s\not\in ss 到变成 ∈s\in ss,先减去原来的代价再加上 ∈s\in ss 里面时计算的代价。

时间复杂度 O(2mm)O(2^mm)O(2mm)

那么 fff 数组的转移就比较简洁了:枚举 sss 二进制下的 111 位置,取较小值。
f(s)=min⁡i∈s{f(s−{i})+∣s∣g(i,s−{i})}f(s)=\min_{i\in s}\Big\{f(s-\{i\})+|s|g(i,s-\{i\})\Big\} f(s)=ismin{f(s{i})+sg(i,s{i})}
到此时空复杂度均为 O(m2m)O(m2^m)O(m2m)

发现空间起飞了。其实观察数据分布就会发现,mmm 的变化只有 111,对空间的限制明显狠于时间。

也就是说,难得的需要来考虑卡一下空间了。

有各种大力优化空间的妙做法,但是从应试角度,以及出题角度,私以为这种做法以及可以应付了:

转移方程中 g(i,s)g(i,s)g(i,s) ,若 i∈si\in sis 则是不合法的,显然不会被用到。

换言之,对于每个 iii,最多只有 2222^{22}222 种状态。

如果只存合法状态,内存就会 /2/2/2,在时间上而言是常数的东西这里就是个大优化了。

考虑怎么减半?

  • 只用让每个 sss 的前 i−1i-1i1 位不动,(s&(1<<i)-1)
  • 其余位置整体右移一位,相当于 /2/2/2(s^(s&(1<<i)-1))>>1
  • 最后把两者加起来即可。

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 23
int n, m, k;
int f[1 << maxn], g[maxn][1 << maxn - 1], cnt[maxn][maxn];
int lowbit( int x ) { return x & -x; }
int main() {scanf( "%d %d %d", &n, &m, &k );for( int i = 1, x, lst = -1;i <= n;i ++ ) {scanf( "%d", &x ); x --;if( ~ lst ) ++ cnt[lst][x];lst = x;}for( int i = 0;i < m;i ++ ) {for( int j = 0;j < m;j ++ )if( i ^ j ) g[i][0] += k * cnt[j][i] - cnt[i][j];for( int s = 1;s < (1 << m);s ++ )if( ! (s >> i & 1) ) {int t = s ^ lowbit( s );int j = __builtin_ffs( s ) - 1;g[i][(s & (1<<i)-1) + ((s ^ (s & (1<<i)-1)) >> 1)] = g[i][(t & (1<<i)-1) + ((t ^ (t & (1<<i)-1)) >> 1)] + (k * cnt[i][j] + cnt[j][i]) - (k * cnt[j][i] - cnt[i][j]);}}memset( f, 0x3f, sizeof( f ) ); f[0] = 0;for( int s = 1;s < (1 << m);s ++ ) {int x = __builtin_popcount( s );for( int i = 0;i < m;i ++ )if( s >> i & 1 ) {int t = s ^ (1 << i);f[s] = min( f[s], f[t] + x * g[i][(t & (1<<i)-1) + ((t ^ (t & (1<<i)-1)) >> 1)] );}}printf( "%d\n", f[(1 << m) - 1] );return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316276.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SP687 REPEATS - Repeats(暂时不会)

SP687 REPEATS - Repeats 题意&#xff1a; 给定字符串&#xff0c;求重复次数最多的连续重复子串 题解&#xff1a; 论文题&#xff0c;暂时不会&#xff0c;搞不清楚原理 代码&#xff1a;

[翻译] ASP.NET Core 利用 Docker、ElasticSearch、Kibana 来记录日志

一步一步指导您使用 ElasticSearch, Kibana, ASP.NET Core 2.1 和 Docker 来记录日志在本教程中&#xff0c;我将向您展示如何启动和运行 ElasticSearch&#xff0c;Kibana 和 ASP.NET Core 2.1在开始之前&#xff0c;让我们来看看 ElasticSearch&#xff0c;Kibana 和 Serilog…

[省选联考 2020 A 卷] 作业题(欧拉反演 + 矩阵树定理 + 高斯消元)

problem luogu-P6624 小 W 刚刚在离散数学课学习了生成树的知识&#xff1a;一个无向图 G(V,E)G(V,E)G(V,E) 的生成树 TTT 为边集 EEE 的一个大小为 ∣V∣−1|V|-1∣V∣−1 的子集&#xff0c;且保证 TTT 的生成子图在 GGG 中连通。 小 W 在做今天的作业时被这样一道题目难住…

P4070 [SDOI2016]生成魔咒

P4070 [SDOI2016]生成魔咒 题意&#xff1a; 有n个字符xi&#xff0c;每次在S的末尾加入一个字符&#xff0c;(一开始S为空)&#xff0c;每次加入xi后的不相同字串有多少个 题解&#xff1a; 做这个题首先要会后缀数组P3809 【模板】后缀排序&#xff0c;还要知道不同的子串…

【学习笔记】WQS二分详解及常见理解误区解释

文章目录应用分析算法分析WQS二分精髓的两点细节&#xff08;博客重点&#xff01;&#xff09;真题分析[国家集训队]Tree Ⅰ忘情星际广播网上很多博客写得模模糊糊的&#xff0c;对我这个新手可是一点都不友好。 昨天一天都在研究这个东西&#xff0c;分享一下自己的拙见。 百…

ASP.NET Core中HTTP管道和中间件的二三事

本文出自《从零开始学ASP.NET CORE MVC》推荐文章&#xff1a;中间件是什么&#xff1f;在.NET Core中的工作原理又是怎样的呢&#xff1f;配置ASP.NET Core请求(Request)处理管道在本视频中&#xff0c;我们将讨论使用中间件组件为asp.net core 应用程序配置请求处理管道。作为…

Codeforces Round #737 (Div. 2)

Codeforces Round #737 (Div. 2) 题号题目知识点AEzzat and Two Subsequences思维&#xff08;略&#xff09;BMoamen and k-subarrays思维(略)CMoamen and XOR二进制DEzzat and Grid线段树思维EAssiut Chess

非平凡回路(bfs)

problem 题目描述 给定一张 nnn 个点的无向图&#xff0c;定义经过一个点 uuu 的非平凡回路为一条从 uuu 出发回到 uuu 的路径&#xff0c;并且至少包含一个简单环。 对于每个点求出经过它的最小非平凡回路长度 lll。 考虑到这个问题很困难&#xff0c;因此你只需要求出 ⌈…

cf1557 C. Moamen and XOR

cf1557 C. Moamen and XOR 题意&#xff1a; 一个n位数&#xff0c;每一位小于2k2^k2k,如果a1&a2&…an>a1⊕a2…⊕an,则获胜 现在给你n和k&#xff0c;问能构造多少个序列是获胜的 题解&#xff1a; 奇偶分类二进制考虑 我们现在认为每个数的第k位都是1 如果n为…

.Net Core Razor 预编译,动态编译,混合编译

预编译预编译是ASP .Net Core的默认方式。在发布时&#xff0c;默认会将系统中的所有Razor视图进行预编译。编译好的视图DLL统一命名为 xxx.PrecompiledViews.dll 或者 xxx.Views.dll动态编译将项目整个配置成动态编译很简单&#xff0c;添加一个配置项目MvcRazorCompileOnPubl…

[CodeForces gym 101630 J] 过路费(最短路)

problem 给定一张图 nnn 个点 mmm 条边&#xff0c;并给定阈值 kkk&#xff0c;以及起终点 s,ts,ts,t。 然后每条边经过都需要支付 www 的花费&#xff0c;形如 (u,v,w)(u,v,w)(u,v,w) 格式给出。 求 s→ts\rightarrow ts→t 的最小花费。 最小花费定义如下&#xff1a; 如…

cf1557D. Ezzat and Grid

cf1557D. Ezzat and Grid 题意&#xff1a; 有n行&#xff0c;每行有10910^9109列&#xff0c;仅仅由0和1构成 现在给你1的存在位置&#xff0c;(i,l,r)表示第i行的第l列到第r列全为1 你可以删除任意一行i&#xff0c;删除后&#xff0c;第i-1行和第i1行为相邻 现在我们要求求…

一张图来看看.NETCore和前后端技术的演进之路

一张图2019年3月10日&#xff0c;在长沙.NET 技术社区组织的技术沙龙《.NET Core和前后端分离那些事儿》上&#xff0c;我们曾经试图通过一系列抽丝剥茧的过程来引导大家在这条基于.NET Core的前后端分离有关的技术路线上持续发散&#xff0c;由于各种原因未能成功&#xff0c;…

【学习笔记】我命由天不由我之随机化庇佑 —— 爬山法 和 模拟退火法

以下均假设最优解是在最低点。 爬山法 爬山算法是一种局部择优的方法&#xff0c;采用启发式方法&#xff0c;是对深度优先搜索的一种改进&#xff0c;它利用反馈信息帮助生成解的决策。 直白地讲&#xff0c;就是当目前无法直接到达最优解&#xff0c;但是可以判断两个解哪…

Strange Memory Gym - 102832F

Strange Memory Gym - 102832F 题意&#xff1a; 有一颗n个节点的树&#xff0c;求下面公式的值&#xff1a; 题解&#xff1a; a ⊕ b c 可以推出a ⊕ c b 那么ai⊕ajalca(i,j)a_{lca(i,j)}alca(i,j)​,可以得到&#xff1a;ai⊕alca(i,j)a_{lca(i,j)}alca(i,j)​aj,ai就…

.net core 使用RSA获取私钥证书并签名

以前我们使用RSA加密主要是使用RSACryptoServiceProvider这个类&#xff0c;在.NET Core中也有这个类&#xff0c;但是这个类并不支持跨平台&#xff0c;所以如果你是用这个类来进行加/解密在windows上运行是完全没有错误的&#xff0c;但是只要你一放到Linux下就会出现异常。查…

2022 联合省选游记 信息奥赛五年退役记

Day0 这可不太美妙&#xff0c;十点就上床睡觉&#xff0c;结果完全睡不着&#xff0c;我妈打呼&#xff0c;加上我当时脑袋也想得多&#xff0c;整个人就挺烦躁的。 翻来覆去可能突然就睡着了&#xff0c;然后醒来虽然没天亮但是我猜至少也有五点多了吧&#xff0c;缓一会看…

CDN流量调度问题(2021CCPC华为云挑战赛)

CDN流量调度问题 题意&#xff1a; 有n个线路&#xff0c;每个线路的任务量为a[i],初始状态下&#xff0c;每个线路起初只有一个节点&#xff0c;每个线路完成任务所需时间为 现在你要给每个线路增加节点&#xff0c;所有增加的节点总数不超过m&#xff0c;第i个线路增加节点…

.NET Core 3.0 Preview 3中关于ASP.NET Core的更新内容

.NET Core 3.0 Preview 3已经推出&#xff0c;它包含了一系列关于ASP.NET Core的新的更新。下面是该预览版的更新列表&#xff1a;Razor组件改进:单项目模板 新的Razer扩展Endpoint路由集成预呈现Razor类库中的Razor组件改进事件处理 Forms & validation运行时编译Worker服…

世界五星级大厨经典菜品集

本blog只是记录C学习以来掉过的一些坑&#xff0c;写下来防止自己下一次再犯&#xff0c;顺便分享 持续更新&#xff0c;到死为止菜品特套1&#xff1a;vector.size() ~ 的使用菜品特套2&#xff1a;if-else的缩进菜品特套3&#xff1a;int范围边界的1ll使用菜品特套4&#xff…