「NOIP2017」宝藏 题解

博客阅读效果更佳


又到了一年一度NOIPCSP-S 赛前复习做真题的时间

于是就遇上了这道题


首先观察数据范围 \(1 \le n \le 12\) ,那么极大可能性是状压 \(\texttt{DP}\) 或者 \(\texttt{DFS}\) 爆搜

但由于这题放在了 \(\texttt{DP}\) 列表里面,于是优先考虑状压

简化题意:

从给定的 \(n\) 个点,\(m\) 条边的有重边的无向联通图中,找出一棵生成树,使得题目所求价值最小

从题目给出的建边价值来看,我们发现一条边的价值跟以下几点有关:

  • 根的位置
  • 当前状态下的树的高度
  • 该边的长度

边的长度不能改变,根的位置并不能很好的作为 \(\texttt{DP}\) 时候的阶段,所以我们考虑以树的高度作为DP的阶段

设根的深度为1

设 \(\texttt{f[i][j]}\) 表示 当前树的高度为 \(i\) ,已经选了的点集的集合为 \(j\),那么状态转移方程即为

\[f[i][j]=\min_{k\ \in \ j}(f[i-1][j \ \mathrm{xor} \ k]+dis[j \ \mathrm{xor} \ k][k]\cdot(i-1))
\]

其中异或操作在这里是取补集的意思,\(\texttt{dis[i][j]}\) 表示从 \(i\) 这个已选点集加上下一层将要选的 \(j\) 这个点集所需要的最小花费

那我们应该如何完善 \(\texttt{dis}\) 数组呢

先给出递推式

\[dis[i][j]=dis[i][j \ \mathrm{xor} \ \mathrm{lowbit}(j)]+\min_{k=1}^{n\ \&\& \ (1<<k)\&i}(d[\log_2\mathrm{lowbit}(j)+1][k])
\]

其中 \(d\) 数组表示第 \(i\) 个点到 第 \(j\) 个点的道路长度(没有则为 \(\infty\) ),\(j\) 为 \(i\) 的补集的任一子集

然后从小到大枚举 \(j\) ,就能够保证顺序正确(因为 \(j \ \mathrm{xor} \ \mathrm{lowbit}(j)\) 一定比 \(j\) 要小)

因为每一次更新只涉及到一个点的更改,所以不难得出这样预处理 \(dis\) 数组的正确性

然后,这题就完了

另外还有几点需要注意的

  • 边最好使用邻接矩阵储存,因为有重边,而且请不要将初值赋得太大,这样会导致在进行动态规划求解的同时溢出,从而导致答案错误

  • 如果按照上面那种朴素的做法来进行求解复杂度有可能不能承受,观察发现我们枚举了许多不必要的子集,所以我们可以换一个方式:

    for(int i=S;i;i=(i-1)&S)

    这样的话所有的 \(i\) 就一定是 \(S\) 的子集

    蒟蒻的理解:不等于 \(S\) 的 \(S\) 的子集一定在 \([0,S)\) 中

    然后或运算可以求出在这当中十进制下数字最大的子集 ,设其为 \(P\),然后其余所有的十进制表示比他小的子集都在\([0,P)\) 当中,如此循环求解,自然能够得到所有的子集

  • 关于状态的一点点优化

    容易发现,当树高为 \(i\) 时,至少需要 \(i\) 个节点,所以所有状态中点的个数小于 \(i\) 的(即二进制位上 \(1\) 的个数小于 \(i\) 的),全部可以不用枚举子集,直接跳过,这对时间复杂度又有了进一步的常数优化。 这可以通过预处理得到。

最后贴一下代码,变量名与上面提到的略有不同

#include<bits/stdc++.h>
using namespace std;
const int maxn=12;
int d[maxn+5][maxn+5];
int g[maxn+5][(1<<maxn)+5];
int f[(1<<maxn)+5][(1<<maxn)+5];
int lg[(1<<maxn)+5];//懒
int q[(1<<maxn)+5],cnt;
int sum[(1<<maxn)+5];
int main()
{
memset(g,63,sizeof g);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=0;i<n;++i)
lg[1<<i]=i;//预处理,因为懒
for(int i=0;i<12;++i)
for(int j=0;j<12;++j)
d[i][j]=1000000;//赋最大值
for(int i=1;i<=m;++i)
{
int a,b,c;
cin>>a>>b>>c;
--a,--b,d[a][b]=d[b][a]=min(d[a][b],c);
}
int x,S=(1<<n)-1;//全集定义
for(int i=1;i<=S;++i)
{
x=i;
while(x) x&=(x-1),++sum[i];
}//预处理每一个状态上点的个数
for(int i=1;i<=S;++i)
{
cnt=0;
for(int j=S^i;j;j=(j-1)&(S^i)) q[++cnt]=j;//由于这样做子集的顺序是从大到小的,不符合DP的顺序,所以要逆序
for(int j=cnt;j>=1;--j)
{
int u=lg[q[j]&-q[j]],e=1000000;
for(int v=0;v<n;++v)
if(1<<v&i) e=min(d[u][v],e);
f[i][q[j]]=f[i][q[j]^(q[j]&-q[j])]+e;
}
}
for(int i=0;i<n;++i) g[1][1<<i]=0;//初始状态
for(int i=2;i<=n;++i)
for(int j=(1<<i)-1;j<=S;++j)//剪枝,这里i的初始状态跳过了肯定不符合的状态
{
if(sum[j]<i) continue;//剪枝,不满足直接跳过
for(int k=j;k;k=(k-1)&j)
g[i][j]=min(g[i][j],g[i-1][j^k]+f[j^k][k]*(i-1));
}
int ans=(1<<30);
for(int i=1;i<=n;++i) ans=min(ans,g[i][S]);//取最小值
cout<<ans<<endl;
return 0;
}

「NOIP2017」宝藏的更多相关文章

  1. loj2318 「NOIP2017」宝藏[状压DP]

    附带其他做法参考:随机化(模拟退火.爬山等等等)配合搜索剪枝食用. 首先题意相当于在图上找一颗生成树并确定根,使得每个点与父亲的连边的权乘以各自深度的总和最小.即$\sum\limits_{i}dep ...

  2. 「NOIP2017」「LuoguP3959」 宝藏(爆搜

    题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 nn 个深埋在地下的宝藏屋, 也给出了这 nn 个宝藏屋之间可供开发的mm 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏. ...

  3. 逛公园「NOIP2017」最短路+DP

    大家好我叫蒟蒻,这是我的第一篇信竞题解blog [题目描述] 策策同学特别喜欢逛公园. 公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园 ...

  4. 2018.11.01 loj#2319. 「NOIP2017」列队(线段树)

    传送门 唉突然回忆起去年去noipnoipnoip提高组试水然后省二滚粗的悲惨经历... 往事不堪回首. 所以说考场上真的有debuffdebuffdebuff啊!!!虽然当时我也不会权值线段树 这道 ...

  5. LOJ2319. 「NOIP2017」列队【线段树】

    LINK 思路 神仙线段树 你考虑怎么样才能快速维护出答案 首先看看一条链怎么做? 首先很显然的思路是维护每个节点的是否出过队 然后对于重新入队的点 直接在后面暴力vector存一下就可以了 最核心的 ...

  6. LOJ2316. 「NOIP2017」逛公园【DP】【最短路】【思维】

    LINK 思路 因为我想到的根本不是网上的普遍做法 所以常数出奇的大,而且做法极其暴力 可以形容是带优化的大模拟 进入正题: 首先一个很显然的思路是如果在合法的路径网络里面存在零环是有无数组解的 然后 ...

  7. 「NOIP2017」「LuoguP3952」 时间复杂度(模拟,栈

    题目描述 小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写程序 ...

  8. loj2314 「NOIP2017」小凯的疑惑[同余最短路or数论]

    这题以前就被灌输了“打表找规律”的思想,所以一直没有好好想这道题,过了一年还不太会qwq.虽然好像确实很简单,但是还是带着感觉会被嘲讽的心态写这个题解...而且还有一个log做法不会... 法1:(一 ...

  9. 【LOJ2316】「NOIP2017」逛公园

    [题目链接] [点击打开链接] [题目概括] 对给定\(K\),起点\(1\)到终点\(n\)中对长度为\([L,L+K]\)的路径计数. \(L\)为\(1\)到\(n\)的最短路长度. [思路要点 ...

随机推荐

  1. Elasticsearch分页查询

    global index global CLIENT index = "guajibao-ipused-2019.10.13" CLIENT = Elasticsearch(hos ...

  2. Resnet-50网络结构详解

    解决的问题: 由于梯度消失,深层网络很难训练.因为梯度反向传播到前面的层,重复相乘可能使梯度无穷小.结果就是,随着网络的层数更深,其性能趋于饱和,甚至迅速下降. 核心思想: 引入一个恒等快捷键(也称之 ...

  3. JVM学习心得—JVM内存模型(个人整理,请勿转载)

    一.运行时数据区域 线程私有的:程序计数器+虚拟机栈+本地方法栈 线程共享的:堆+方法区(运行时常量池)+直接内存(非运行时数据区的一部分) *JDK1.8后将方法区废除,新增元空间. 1.1 程序计 ...

  4. AI推理与Compiler

    AI推理与Compiler AI芯片编译器能加深对AI的理解, AI芯片编译器不光涉及编译器知识,还涉及AI芯片架构和并行计算如OpenCL/Cuda等.如果从深度学习平台获得IR输入,还需要了解深度 ...

  5. 硬件delay评估表

    硬件delay评估表 硬件延时评估表用于快速评估一个模型在特定硬件环境和推理引擎上的推理速度. Bw 主要用于定义PaddleSlim支持的硬件延时评估表的格式. 概述 硬件延时评估表中存放着所有可能 ...

  6. 用OpenCV4实现图像的超分别率

    用OpenCV4实现图像的超分别率 本实验原文链接:· https://arxiv.org/pdf/1807.06779.pdf 原文摘要 单图像超分辨率(SISR)的主要挑战是如何恢复微小纹理等高频 ...

  7. 机器学习PAI产品架构

    机器学习PAI产品架构 本文介绍PAI的产品架构. 如上图所示,PAI的业务架构分为五层: 基础设施层:包括CPU.GPU.FPGA及NPU. 计算引擎和容器服务层:包括MaxCompute.EMR. ...

  8. Ryzen 4000'Vermeer' CPU和Radeon RX'Big Navi'图形卡

    Ryzen 4000'Vermeer' CPU和Radeon RX'Big Navi'图形卡 来自中国媒体的多篇报道表明,AMD都准备在2020年第四季度初推出其下一代Ryzen 4000'Zen 3 ...

  9. 5G和AI机器人平台为工业4.0和无人机提供服务

    5G和AI机器人平台为工业4.0和无人机提供服务 Qualcomm 5G and AI robotics platform delivers for Industry 4.0 and drones 高 ...

  10. python 数据写入json文件时中文显示Unicode编码问题

    一.问题描述 import json dir = { '春晓':'asfffa', '春眠不觉晓' : '处处闻啼鸟', '夜来风雨声' : 56789, 'asdga':'asdasda' } fp ...