传送门

这是蓝书上状压的例题啊,怎么会出现在模拟赛里

不过就算原题我也没把握写对

核心思路:

先令\(dp[s]\)为当前状态为\(s\)时的总花费最小值,\(cnt[s][i]\)为这个方案中由根节点(赞助商打通的节点)到\(i\)节点最少经过的房间数

此题转移较为麻烦,转移时需要知道当前每个点经过了几个房间

考虑对每个状态开个数组记录到此状态每个点经过了几个房间

注意这个\(cnt\)数组是\(dp\)值的附属物,所以\(dp\)值更新的时候\(cnt[]\)需要跟着覆写过去

然后就是一个状压求最小值的板子了

怎么可能这么简单,这里的转移覆写的后效性怎么说?

然而事实是,这里每次转移取最小值更新根本没有后效性

所以考场上直接猜个结论开始写可以有100pts拿 (弥天大雾

好了这个后效性的有无是此题难点

因为如果真的有后效性的话我们并不知道如何消除它,所以我们试着去证明这里不必处理后效性,杀敌于无形之中

首先考虑我们所说这里的后效性是什么:

放张图:

令赞助商打通的是节点1

那么对于这个节点3,它会被1-2-3这条路径更新,\(cnt=3\)

而1-3这条路径虽然权值更大,但其\(cnt=2\)

对于后续的更新无法判断谁更优,

那这里直接由1-2-3把3更新掉不就有后效性了吗?

然而我们更新3的实质是\(dp[0111] = min(dp[0011], dp[0101])\)

我们所想象的后效性是在节点1,2,3均打通后向4转移会有后效性

谁说我们一定要先打通1,2,3才能向4转移了?

考虑节点4的更新,\(dp[1111] = min(dp[0111], dp[1101])\)(其它状态不合法,已舍去)

由方程知这里可以也考虑了1-3-4-2的方案,推广到所有情况,会考虑少一条边的所有可能,并没有后效性

同样由方程知,我们在状压时实际考虑了所有点向这个点所有可能的连边方案,

而我们所想的「后效性」,实质上是「在已固定了几条连边后出现的后效性」

则我们直接列出方程

\[dp[s|(1<<v)] = min(dp[s|(1<<v)], dp[s]+edge.val*cnt[s][i])
\]

而这里的cnt数组是dp值的附属物,在转移的同时要把\(cnt[s]\)覆写过去

然后按方程转移即可

哦对了还有这个题里全是重边,建议开邻接矩阵存边

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
} int n, m;
ll dp2[13][1<<14], val[15];
int cnt[13][1<<14][13];
int head[20], size;
int mp[15][15];
inline void add(int s, int t, int w) {mp[s][t]=min(mp[s][t], w); mp[t][s]=min(mp[t][s], w);} signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif
memset(dp2, 127, sizeof(dp2));
memset(mp, 127, sizeof(mp)); n=read(); m=read();
int lim=1<<n;
for (int i=1,u,v,w; i<=m; ++i) {u=read(); v=read(); w=read(); add(u, v, w); add(v, u, w);}
for (int begin=0; begin<n; ++begin) {
dp2[begin][1<<begin] = 0;
cnt[begin][1<<begin][begin] = 1;
ll *dp=dp2[begin]; for (int s=1; s<lim; ++s) {
for (int j=0; j<n; ++j) {
if (!(s&(1<<j))) continue;
for (int i=1,v; i<=n; ++i) {
if (j+1==i || mp[j+1][i]>500010) continue;
v = i-1;
if (s&(1<<v)) continue; if (dp[s]+1ll*mp[j+1][i]*(cnt[begin][s][j]) < dp[s|(1<<v)]) {
dp[s|(1<<v)] = min(dp[s|(1<<v)], dp[s]+1ll*mp[j+1][i]*(cnt[begin][s][j]));
for (int k=0; k<n; ++k) cnt[begin][s|(1<<v)][k] = cnt[begin][s][k];
cnt[begin][s|(1<<v)][v] = cnt[begin][s][j]+1;
}
}
}
}
}
ll ans=INF;
for (int i=0; i<n; ++i) ans = min(ans, dp2[i][lim-1]);
printf("%lld\n", ans); return 0;
}

题解 [NOIP2017 提高组]宝藏的更多相关文章

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

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

  2. [NOIp2017提高组]宝藏

    #include<cstdio> #include<cctype> #include<algorithm> inline int getint() { regist ...

  3. [NOIP2017 提高组] 宝藏

    考虑到这种对于某种操作顺序有一个权值. 且这个权值有一个\(O(n)\)或者更好的复杂度求出. 求最值. 那可以用模拟退火. #include<iostream> #include< ...

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

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

  5. [NOIp2017提高组]列队

    [NOIp2017提高组]列队 题目大意 一个\(n\times m(n,m\le3\times10^5)\)的方阵,每个格子里的人都有一个编号.初始时第\(i\)行第\(j\)列的编号为\((i-1 ...

  6. JZOJ 5196. 【NOIP2017提高组模拟7.3】B

    5196. [NOIP2017提高组模拟7.3]B Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  7. JZOJ 5197. 【NOIP2017提高组模拟7.3】C

    5197. [NOIP2017提高组模拟7.3]C Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  8. JZOJ 5195. 【NOIP2017提高组模拟7.3】A

    5195. [NOIP2017提高组模拟7.3]A Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  9. JZOJ 5184. 【NOIP2017提高组模拟6.29】Gift

    5184. [NOIP2017提高组模拟6.29]Gift (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed ...

随机推荐

  1. mysql,mongodb,redis区别

    MongoDB: 它是一个内存数据库,数据都是放在内存里面的. 对数据的操作大部分都在内存中,但 MongoDB 并不是单纯的内存数据库. MongoDB 是由 C++ 语言编写的,是一个基于分布式文 ...

  2. 探索互斥锁 Mutex 实现原理

    Mutex 互斥锁 概要描述 mutex 是 go 提供的同步原语.用于多个协程之间的同步协作.在大多数底层框架代码中都会用到这个锁. mutex 总过有三个状态 mutexLocked: 表示占有锁 ...

  3. python03篇 字符串常用方法和文件操作(一)

    一.字符串常用方法 s1 = ' abcsfsfaadfdd ' s = s1.strip() print(s) print(len(s.strip())) print(s.count('a')) # ...

  4. Outlook配置163邮箱

    一.在163邮箱设置处设置POP3/SMTP/IMAP 二.开启客户端授权码 三.打开Outlook,选择手动设置 选择POP/IMAP 密码是上文中的授权码 点击其它设置,勾选以下选项 点击完成即可

  5. H3C交换机常用命令

    选择多个端口: interface range ethernet 1/0/1 to ethernet 1/0/12 vlan-interface1 常用命令 密码修改:  查看是否有相应的用户名:di ...

  6. 团队开发day07

    开始整合项目,测试登录,注册,搜索功能, 在安卓中数据处理存在个别错误,功能逻辑有个别不正确 进行修改和完善,添加二次确认退出

  7. python3执行.sql文件

    这个脚本主要是遍历执行文件夹下的sql文件,但是没有辨别文件的格式,所以文件夹下只能够放.sql文件,否则会报错哈. 我的sql文件夹与执行的文件平级,所以dir_path就是sql,大家依照自己的路 ...

  8. 公有云上构建云原生 AI 平台的探索与实践 - GOTC 技术论坛分享回顾

    7 月 9 日,GOTC 2021 全球开源技术峰会上海站与 WAIC 世界人工智能大会共同举办,峰会聚焦 AI 与云原生两大以开源驱动的前沿技术领域,邀请国家级研究机构与顶级互联网公司的一线技术专家 ...

  9. SpringBoot之yaml语法及静态资源访问

    配置文件-yaml 在spring Boot开发中推荐使用yaml来作为配置文件. 基本语法: key: value:kv之间有空格 大小写敏感 使用缩进表示层级关系 缩进不允许使用tab,只允许空格 ...

  10. xampp搭建开源项目iwebshop后,服务器重启后再启动xampp显示组件都启动ok,但是实际启动失败解决办法

    最近用xampp搭建了开源商城项目iwebshop,刚搭建完没问题,可是周一来因为服务器重启了,我再启动xampp,显示组件都启动ok了,但是用linux命令查看相关组件的进程时,发现实际没启动起来, ...