题解 P6622 [省选联考 2020 A/B 卷] 信号传递
洛谷 P6622 [省选联考 2020 A/B 卷] 信号传递
题解
某次模拟赛的T2,考场上懒得想正解 (其实是不会QAQ),
打了个暴力就骗了\(30pts\) 就火速溜了,参考了一下某位强者的题解
大概懂了一点思路,有亿点毒瘤。。。
数据范围是\(m<=23\) 的 明显是个状压么!!!
数组代表意义
令\(f[i]\)表示,当已经确定的信号站集合为\(i\)时,此时已确定花费的最小值是多少。
此时考虑两个转移:
将左向右方向中继变换为先由初始节点中继到\(0\)号节点,再由\(0\)号节点中继到目标节点
将从右向左的中继变换为初始节点以\(−1\)的花费中继到\(0\)号节点,再由\(0\)号节点中继到目标节点
\(cnt_{i,j}=x\)表示有\(x\)个需要从\(i\)转移到\(j\)
\(val\)的含义在下文中给出,这里需要注意一下\(val\)的空间\(M*(2^{M-1})\)刚刚好,不要开太大,否则会\(MLE\)
\(las\)表示上一个的坐标,用来更新\(cnt\)值
const int M=23;
int n,m,K,las,cnt[M+5][M+5],val[M+5][1<<(M-1)],f[1<<M];
初始化
拿\(cnt[i][j]\)存一下从\(i\)到\(j\)的总数,也就是下面这个式子:
$cnt_{i,j}= \sum_{k=1}^{n-1} [S_k=i][S_{k+1}=j] $
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
x--;
if(i>1)
cnt[las][x]++;
las=x;
}
算法主体
然后对于题面推算一下每个位置对于最终答案的加值,如下:
\(\begin{aligned}ans&=\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}K*(i+j)\\&=\sum_{i=1}^m-i\sum_{j=i+1}^mcnt_{id_i,id_j}+\sum_{i=1}^mi\sum_{j=1}^{i-1}cnt_{id_j,id_i}+K*\sum_{i=1}^mi\sum_{j=1}^{i-1}cnt_{id_i,id_j}+K*\sum_{i=1}^mi\sum_{j=i+1}^mcnt_{id_j,id_i}\\&=\sum_{i=1}^mi\left(\sum_{j=i+1}^m\left(K\cdot cnt_{id_j,id_i}-cnt_{id_i,id_j}\right)+\sum_{j=1}^{i-1}\left(K\cdot cnt_{id_i,id_j}+cnt_{id_j,id_i}\right)\right)\end{aligned}\)
然后,用\(val[i][j]\)简化一下上面的式子
\(vaj_{i,j}=\sum_{k\notin,k!=i}(K*cnt_{id_k,id_i}-cnt_{id_i,id_k})+\sum_{k\in j}(K*cnt_{id_i,id_k}+cnt_{id_k,id_i})\)
在处理\(val\)数组时可以发现对于\(1\)~\(i-1\)状态的是没有必要变动的,因此只需要将i之后的更改可以了
\((j\) &$ ( (1<<i)-1)$
表示前\(1\)~\(i-1\)状态不变
\(((j\)^\((j\)&\(((1<<i)-1)))>>1)\)
表示对于\(i+1\)~\(n\)状态更新,向右移一位
更改时要从\(j\)状态除去一个\(lowbit\)转移过来原因见上,
剩下的就是关于上面公式的使用了
for(int i=0;i<m;i++)
{
for(int j=0;j<m;j++)//对于0状态进行初始化
if(j!=i)
val[i][0]+=K*cnt[j][i]-cnt[i][j];
for(int j=1;j<(1<<m);j++)//更新后面状态
if(!(j&(1<<i)))
{
int x=j^lowbit(j),y=__builtin_ffs(j)-1;//求最后一位1
val[i][(j&((1<<i)-1))+((j^(j&((1<<i)-1)))>>1)]=val[i][(x&((1<<i)-1))+((x^(x&((1<<i)-1)))>>1)]+K*cnt[i][y]+cnt[y][i]+cnt[i][y]-K*cnt[y][i];
}
}
最后就是对于\(dp\)方程的转移了,和上面推的式子一样,再此不做过多赘述。
for(int i=1;i<(1<<m);i++)
{
f[i]=INT_MAX;//初始化赋最大值
int sum=__builtin_popcount(i);//求i状态中1的数量
for(int j=0;j<m;j++)
if(i&(1<<j))
{
int x=i^(1<<j);
f[i]=min(f[i],f[x]+sum*val[j][(x&(1<<j)-1)+((x^x&(1<<j)-1)>>1)]);
}
}
\(code\)
#include<bits/stdc++.h>
using namespace std;
const int M=23;
int n,m,K,las,cnt[M+5][M+5],val[M+5][1<<(M-1)],f[1<<M];
int lowbit(int x)
{
return x&(-x);
}
int main()
{
scanf("%d%d%d",&n,&m,&K);
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
x--;
if(i>1)
cnt[las][x]++;
las=x;
}
for(int i=0;i<m;i++)
{
for(int j=0;j<m;j++)
if(j!=i)
val[i][0]+=K*cnt[j][i]-cnt[i][j];
for(int j=1;j<(1<<m);j++)
if(!(j&(1<<i)))
{
int x=j^lowbit(j),y=__builtin_ffs(j)-1;
val[i][(j&((1<<i)-1))+((j^(j&((1<<i)-1)))>>1)]=val[i][(x&((1<<i)-1))+((x^(x&((1<<i)-1)))>>1)]+K*cnt[i][y]+cnt[y][i]+cnt[i][y]-K*cnt[y][i];
}
}
for(int i=1;i<(1<<m);i++)
{
f[i]=INT_MAX;
int sum=__builtin_popcount(i);
for(int j=0;j<m;j++)
if(i&(1<<j))
{
int x=i^(1<<j);
f[i]=min(f[i],f[x]+sum*val[j][(x&(1<<j)-1)+((x^x&(1<<j)-1)>>1)]);
}
}
printf("%d",f[(1<<m)-1]);
return 0;
}
完结撒花\(QAQ\)
题解 P6622 [省选联考 2020 A/B 卷] 信号传递的更多相关文章
- luoguP6622 [省选联考 2020 A/B 卷] 信号传递(状压dp)
luoguP6622 [省选联考 2020 A/B 卷] 信号传递(状压dp) Luogu 题外话: 我可能是傻逼, 但不管我是不是傻逼, 我永远单挑出题人. 题解时间 看数据范围可以确定状压dp. ...
- luoguP6619 [省选联考 2020 A/B 卷]冰火战士(线段树,二分)
luoguP6619 [省选联考 2020 A/B 卷]冰火战士(线段树,二分) Luogu 题外话1: LN四个人切D1T2却只有三个人切D1T1 很神必 我是傻逼. 题外话2: 1e6的数据直接i ...
- [省选联考 2020 A/B 卷] 冰火战士
一.题目 点此看题 二.解法 其实这道题也不是特别难吧 \(......\) 但树状数组上二分是我第一次见. 我们把冰人和火人都按温度排序,那么考虑一个分界线 \(x\) ,问题就是求冰数组 \(x\ ...
- [省选联考 2020 A 卷] 组合数问题
题意 [省选联考 2020 A 卷] 组合数问题 想法 自己在多项式和数论方面还是太差了,最近写这些题都没多少思路,看完题解才会 首先有这两个柿子 \(k*\dbinom{n}{k} = n*\dbi ...
- luoguP6623 [省选联考 2020 A 卷] 树(trie树)
luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...
- luoguP6620 [省选联考 2020 A 卷] 组合数问题(斯特林数)
luoguP6620 [省选联考 2020 A 卷] 组合数问题(斯特林数) Luogu 题外话: LN切这题的人比切T1的多. 我都想到了组合意义乱搞也想到可能用斯特林数为啥还是没做出来... 我怕 ...
- luoguP6624 [省选联考 2020 A 卷] 作业题(莫比乌斯反演,矩阵树定理)
luoguP6624 [省选联考 2020 A 卷] 作业题(莫比乌斯反演,矩阵树定理) Luogu 题外话: Day2一题没切. 我是傻逼. 题解时间 某种意义上说刻在DNA里的柿子,大概是很多人学 ...
- [省选联考 2021 A/B 卷] 卡牌游戏
垃圾福建垫底选手来看看这题. 大家怎么都写带 \(log\) 的. 我来说一个线性做法好了. 那么我们考虑枚举 \(k\) 作为翻转完的最小值. 那么构造出一个满足条件的操作,我们在 \(a_i\) ...
- [题解] LOJ 3300 洛谷 P6620 [省选联考 2020 A 卷] 组合数问题 数学,第二类斯特林数,下降幂
题目 题目里要求的是: \[\sum_{k=0}^n f(k) \times X^k \times \binom nk \] 这里面出现了给定的多项式,还有组合数,这种题目的套路就是先把给定的普通多项 ...
随机推荐
- Mybatis最终搭建
框架搭建的流程1. 导入jar2. 准备属性文件和配置文件3. 编写数据库的表和类4. 为类编写一个XxxMapper接口5. 编写接口对应的映射文件XxxMapper.xml6. 根据接口的方法, ...
- spring mvc简单使用
spring mvc pom.xml依赖与插件 导入servlet.springmvc.Jackson的依赖,编译插件.tomcat <?xml version="1.0" ...
- 简单介绍下自动化框架:Robot Framework
一.简介: Robot Framework:Robot Framework是由Python编写的一款功能丰富并且扩展性强的自动化测试框架,也可以在Java和 .NET 上运行. HttpRunner: ...
- NumPy之:ndarray中的函数
NumPy之:ndarray中的函数 目录 简介 简单函数 矢量化数组运算 条件逻辑表达式 统计方法 布尔数组 排序 文件 线性代数 随机数 简介 在NumPy中,多维数组除了基本的算数运算之外,还内 ...
- [bug] vscode output 输出乱码
参考 https://blog.csdn.net/qq_34192032/article/details/105077173 https://blog.csdn.net/a19990412/artic ...
- [DB] 关系型数据库
名词 数据库(database):保存有组织的数据的容器,是通过DBMS创建的容器 表(table):某种特定类型数据的结构化清单 元组(tuple):行,一条数据库记录,对应一个事物 属性(prop ...
- 第3期:Too many open files以及ulimit的探讨
第3期:Too many open files以及ulimit的探讨 毛帅 Java.AI.互联网.金融 10 人赞同了该文章 Too many open files是Java常见的异常,通常是由于系 ...
- echo -n -e "请输入重启间隔的时间(分钟):\t"
echo -n -e "请输入重启间隔的时间(分钟):\t"read interval##echo -n "Your choice is " # 加上 -n 可 ...
- VMware vCenter重置web console SSO登录密码
On a Windows Platform Services Controller or vCenter Server with Embedded Platform Services Controll ...
- IT菜鸟之DHCP
DHCP 动态主机配置协议(Dynamic host configuration protocol) 作用:分配网络地址 选项: excluded-address 排除地址 pool IP地址池(网段 ...