P3959 [NOIP2017 提高组] 宝藏

不难发现最后的路径一定会构成一棵树。由于每条路的贡献与与其深度有关,故考虑设计与深度有关的状态。由于数据范围很小,考虑状态压缩 DP,每次扩展一层。

设状态 \(f[i][j]\) 表示目前扩展到第 \(i\) 层,所有节点的状态为 \(j\)。若第 \(k\) 位为 \(1\),则表示节点 \(k\) 已经被打通;若第 \(k\) 位为 \(0\),则表示节点 \(k\) 未被打通。记状态 \(k\) 转移到状态 \(j\) 经过的边权之和为 \(cost(k,j)\),不难得到如下转移方程:

\[f[i][j]=\min(f[i][j],f[i-1][k]+cost(k,j)\times(i-1))
\]

接下来,考虑预处理出两个数组 \(cost(k,j)\) 与 \(pos(k,j)\),表示状态 \(k\) 转移到状态 \(j\) 经过的边权之和为 \(cost(k,j)\) 与可行性。再预处理一个数组 \(ex(i)\),表示状态 \(i\) 可以扩展的所有点(包括原有点)的状态集合。若第 \(k\) 位为 \(1\),则表示节点 \(k\) 可以被扩展;若第 \(k\) 位为 \(0\),则表示节点 \(k\) 不可以被扩展。

\(ex(i)\) 并不难预处理,只需要枚举已有节点的每一条边,能扩展到的标记为 \(1\) 即可。有了 \(ex(i)\) 后,我们发现 \(pos(k,j)\) 也不难预处理。当且仅当 \(k\) 是 \(j\) 的子集且 \(j\) 是 \(ex(k)\) 的子集时,\(pos(k,j)=1\)。判断子集可以用位运算来实现,若 \(j\&k=k\),则 \(k\) 是 \(j\) 的子集。

接下来,考虑求出满足 \(pos(k,j)\) 的 \(cost(k,j)\)。考虑枚举状态 \(j\) 中未扩展的点,枚举从 \(k\) 中的点到这一个点的边,取边权最小值为贡献。最后,将每一个未扩展的点的贡献加和,即为 \(cost(k,j)\)。预处理之后,转移也比较显然。

时间复杂度为 \(O(m2^{n}+n3^n)\),其中 \(3^n\) 是枚举子集的时间复杂度。

#include <bits/stdc++.h>
using namespace std;
int n,m,u,v,d,h[30000],ex[5000],cst[5000][5000],f[20][5000],ans=1e9;
vector<int>to[20],dis[20];
bool pos[5000][5000];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&d);
to[u].push_back(v),dis[u].push_back(d);
to[v].push_back(u),dis[v].push_back(d);
}
for(int i=0;i<=(1<<n)-1;i++)
{
ex[i]=i;
for(int j=0;j<n;j++)
if(i&(1<<j))
{
int s=to[j+1].size();
for(int k=0;k<s;k++)ex[i]|=(1<<(to[j+1][k]-1));
}
}
for(int i=0;i<=(1<<n)-1;i++)
for(int j=0;j<=(1<<n)-1;j++)
if((j|ex[i])==ex[i]&&(i|j)==j&&i!=j)
{
pos[i][j]=1;
for(int k=0;k<n;k++)
if(!(i&(1<<k))&&(j&(1<<k)))
{
int mi=1e9,s=to[k+1].size();
for(int l=0;l<s;l++)
if((i&(1<<(to[k+1][l]-1))))mi=min(mi,dis[k+1][l]);
cst[i][j]+=mi;
}
}
for(int i=0;i<=n;i++)
for(int j=0;j<=(1<<n)-1;j++)
f[i][j]=1e9;
for(int i=1;i<=n;i++)
f[0][(1<<(i-1))]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=(1<<n)-1;j++)
for(int k=0;k<=(1<<n)-1;k++)
if(pos[k][j]&&f[i-1][k]!=1e9)f[i][j]=min(f[i][j],f[i-1][k]+cst[k][j]*i);
for(int i=0;i<=n;i++)ans=min(ans,f[i][(1<<n)-1]);
printf("%d\n",ans);
return 0;
}

Luogu P3959 [NOIP 2017 提高组] 宝藏 题解的更多相关文章

  1. NOIP 2017 提高组 day1t2 时间复杂度

    P3952 时间复杂度 标签 NOIp提高组 2017 时空限制 1000ms / 128MB 小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂 ...

  2. NOIP2017[提高组] 宝藏 题解

    解析 我们观察范围可以发现n非常的小,(一般来说不是搜索就是状压dp)所以说对于这题我们可以用记忆化搜索或者dp,我们发现起点不同那么最终答案也就不同,也就是说答案是跟起点有关的,于是我们便可以想到去 ...

  3. 【NOIP 2017 提高组】列队

    题目 有一个 \(n\times m\) 的方阵,每次出来一个人后向左看齐,向前看齐,询问每次出来的人的编号. \(n\le 3\times 10^5\) 分析 我们考虑离队本质上只有两种操作: 删除 ...

  4. NOIP 2008提高组第三题题解by rLq

    啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...

  5. NOIP 2014 提高组 题解

    NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法 ...

  6. NOIP 2001 提高组 题解

    NOIP 2001 提高组 题解 No 1. 一元三次方程求解 https://vijos.org/p/1116 看见有人认真推导了求解公式,然后猥琐暴力过的同学们在一边偷笑~~~ 数据小 暴力枚举即 ...

  7. 【题解】NOIP2017 提高组 简要题解

    [题解]NOIP2017 提高组 简要题解 小凯的疑惑(数论) 不讲 时间复杂度 大力模拟 奶酪 并查集模板题 宝藏 最优解一定存在一种构造方法是按照深度一步步生成所有的联通性. 枚举一个根,随后设\ ...

  8. noip 2014 提高组初赛

    noip 2014 提高组初赛 一. TCP协议属于哪一层协议( ) A. 应用层 B. 传输层 C. 网络层 D. 数据链路层 B TCP(传输控制协议) 若有变量int a; float: x, ...

  9. [NOIp 1998 提高组]Probelm 2 连接多位数【2011百度实习生笔试题】

    /*====================================================================== [NOIp 1998 提高组]Probelm 2 连接 ...

  10. 最优贸易 NOIP 2009 提高组 第三题

    题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...

随机推荐

  1. 配置springmvc的springmvc.xml

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  2. Rocketmq 如何保证消息的可用性/可靠性/不丢失呢 ?

    如何保证消息的可用性/可靠性/不丢失呢 ? 消息可能在哪些阶段丢失呢?可能会在这三个阶段发生丢失:生产阶段.存储阶段.消费阶段 生产阶段 在生产阶段,主要通过请求确认机制,来保证消息的可靠传递 1.同 ...

  3. python读取文件夹内所有图片名称,随机设置为桌面壁纸且把设置后的图片移到其他文件夹内的方法

    关键词:读取文件夹.读取文件.操作系统.设置壁纸.移动文件 预期实现如下几个步骤 1.获取指定文件夹内所有图片名 2.随机取一张图片设置为壁纸 3.设置为壁纸的图片移动到另外一个文件夹中 第一步,获取 ...

  4. MySQL 的查询优化器如何选择执行计划?

    MySQL 的查询优化器负责决定如何执行 SQL 查询,它会根据多个因素选择最优的执行计划.查询优化器的目标是选择一个成本最低.性能最优的执行计划,以便高效地处理查询.执行计划的选择是基于 MySQL ...

  5. 经典常用SQL查询语句和常见问题

    一.基础 1.常用sql: ------------------------ // mysql改root密码 mysqladmin -u用户名 -p旧密码 password 新密码 # ---more ...

  6. cmd /k 解决cmd命令闪退问题

    cmd /k 的含义是执行后面的命令,并且执行完毕后保留窗口. & 是连接多条命令.PAUSE 表示运行结束后暂停,等待一个任意按键.EXIT 表示关闭命令行窗口.如果使用 cmd /c 就可 ...

  7. Fastjson命令执行漏洞复现2(fastjson <=1.2.47)

    一.搭建环境: 第一种:Docker一键拉取环境 htttps://github.com/vulhub/vulhub/tree/master/fastjson/1.2.47-rce 第二种:tomac ...

  8. 【SQL周周练】一句 SQL 如何帮助 5 个人买到电影院最好的座位?

    大家好,我是"蒋点数分",多年以来一直从事数据分析工作.从今天开始,与大家持续分享关于数据分析的学习内容. 本文是第 3 篇,也是[SQL 周周练]系列的第 3 篇.该系列是挑选或 ...

  9. DNSPY调试引用dll

    (1) 点击"调试",选择需要调试的可执行程序 (2) 点击"确定"后,打开程序,再点击"调试"-"窗口"-模块 (3) ...

  10. Data aggregation and group operations in pandas

    Data aggregation and group operations in pandas After loading,merging and preparing a dataset,you ma ...