题面:[NOIP2017]宝藏

题面:

  首先我们观察到,如果直接DP,因为每次转移的代价受上一个状态到底选了哪些边的影响,因此无法直接转移。

  所以我们考虑分层DP,即每次强制现在加入的点的距离为k(可能实际上小于k),这样就可以忽略掉上个状态选了哪些边的影响了。

  所以这样为什么是正确的呢?

  设f[i][j]表示DP到第i层,状态为j的最小代价。(即每层离起点最远的点的距离为i - 1,所以下次转移的点距离为i)

  那么如果一个点被错误的计算了代价,当且仅当这个点离起点的距离小于i,但我们依然按照i的距离来计算了代价。

  那么可以证明,这个点一定会在正确的层数被计算一次(i之前的某一层),那么由于当前层数导致代价被多算,因此肯定没那么优,所以不会对答案造成影响。

  因此我们直接DP即可。

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 15
#define ac 12000
#define inf 2139062143
#define LL long long int n, m, maxn, ans = inf;
int f[AC][ac], in[AC], g[AC][AC], dis[ac][AC]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline void upmin(int &a, int b){
if(b < a) a = b;
} void pre()
{
n = read(), m = read(), maxn = ( << n) - ;
memset(g, , sizeof(g));
for(R i = ; i <= m; i ++)
{
int a = read(), b = read(), c = read();
upmin(g[a][b], c), upmin(g[b][a], c);
}
int tmp = ;
for(R i = ; i <= n; i ++)
in[i] = tmp, tmp <<= , g[i][i] = ;
} void get()//获取所有联通块到各个点的距离,预处理可以降低复杂度
{
memset(dis, , sizeof(dis));
for(R k = ; k <= maxn; k ++)
{
for(R i = ; i <= n; i ++)//枚举集合内的一点
{
if(!(k & in[i])) continue;
for(R j = ; j <= n; j ++)
{
if(k & in[j]) dis[k][j] = ;
else upmin(dis[k][j], g[i][j]);
}
}
}
} void work()
{
memset(f, , sizeof(f));
for(R k = ; k <= n + ; k ++)//枚举当前层(走下一步的最远距离)
{
for(R i = ; i <= n; i ++) f[k][in[i]] = ;
upmin(ans, f[k][maxn]);
for(R i = ; i <= maxn; i ++)//枚举状态
{
if(f[k][i] == inf) continue;//不判断这个可能会爆int
int s = i ^ maxn;//获取补集
for(R j = s; j; j = (j - ) & s)//枚举补集的子集
{
int tmp = ;bool flag = true;
for(R l = ; l <= n; l ++)
{
if(!(j & in[l])) continue;//如果不在这个子集中就跳过
if(dis[i][l] == inf) {flag = false; break;}
tmp += k * dis[i][l];
}
if(flag) upmin(f[k + ][i | j], f[k][i] + tmp);
}
}
}
printf("%d\n", ans);
} int main()
{
// freopen("in.in", "r", stdin);
pre();
get();
work();
// fclose(stdin);
return ;
}

[NOIP2017]宝藏 子集DP的更多相关文章

  1. [NOIP2017]宝藏 状压DP

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

  2. NOIP2017宝藏 [搜索/状压dp]

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

  3. 【比赛】NOIP2017 宝藏

    这道题考试的时候就骗了部分分.其实一眼看过去,n范围12,就知道是状压,但是不知道怎么状压,想了5分钟想不出来就枪毙了状压,与AC再见了. 现在写的是状压搜索,其实算是哈希搜索,感觉状压DP理解不了啊 ...

  4. 【题解】NOIP2017逛公园(DP)

    [题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n​节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...

  5. [BZOJ4416][SHOI2013]阶乘字符串(子集DP)

    怎么也没想到是子集DP,想到了应该就没什么难度了. 首先n>21时必定为NO. g[i][j]表示位置i后的第一个字母j在哪个位置,n*21求出. f[S]表示S的所有全排列子序列出现的最后末尾 ...

  6. 「BZOJ1924」「SDOI2010」 所驼门王的宝藏 tarjan + dp(DAG 最长路)

    「BZOJ1924」[SDOI2010] 所驼门王的宝藏 tarjan + dp(DAG 最长路) -------------------------------------------------- ...

  7. loj 300 [CTSC2017]吉夫特 【Lucas定理 + 子集dp】

    题目链接 loj300 题解 orz litble 膜完题解后,突然有一个简单的想法: 考虑到\(2\)是质数,考虑Lucas定理: \[{n \choose m} = \prod_{i = 1} { ...

  8. hdu 5823 color II —— 子集DP

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5823 看博客:http://www.cnblogs.com/SilverNebula/p/5929550. ...

  9. BZOJ 4006 [JLOI2015]管道连接(斯坦纳树+子集DP)

    明显是一道斯坦纳树的题. 然而这题只需要属性相同的点互相连接. 我们还是照常先套路求出\(ans[s]\). 然后对\(ans[s]\)做子集DP即可. 具体看代码. #include<iost ...

随机推荐

  1. dva 路由跳转

    1.从props取出并传递history 取 const { history } = this.props 用 <button onClick={ () => history.push(' ...

  2. Oracle存储过程练习题

    1.1.创建一个过程,能向dept表中添加一个新记录.(in参数) 创建过程 create or replace procedure insert_dept ( num_dept in number, ...

  3. 使用手机登录OWA修改密码的问题

    最近发现使用手机端登录OWA,安卓手机是可以修改密码的,如图1,但是iPhone就不成,safari和第三方都不可以,如图二. 图一 图二

  4. 2018科大讯飞AI营销算法大赛全面来袭,等你来战!

    AI技术已成为推动营销迭代的重要驱动力.AI营销高速发展的同时,积累了海量的广告数据和用户数据.如何有效应用这些数据,是大数据技术落地营销领域的关键,也是检测智能营销平台竞争力的标准. 讯飞AI营销云 ...

  5. 软工2017第六周团队协作——个人PSP

    10.20 --10.26本周例行报告 1.PSP(personal software process )个人软件过程. 类型 任务 开始时间                结束时间 中断时间 实际用 ...

  6. UML设计(团队作业)

    UML设计 一.团队信息 1.队名 读完文章再睡觉 2.团队成员的学号与姓名 学号 姓名 211606381 吴伟华(队长) 211606369 蔺皓雯 211606340 杨池宇 211606372 ...

  7. TCP 的有限状态机

    TCP 有限状态机的图中每一个方框都是 TCP 可能具有的状态. 每个方框中的大写英文字符串是 TCP 标准所使用的 TCP 连接状态名. 状态之间的箭头表示可能发生的状态变迁. 箭头旁边的字,表明引 ...

  8. node中的__dirname

    先说结论:__dirname指的是当前文件所在文件夹的绝对路径. 测试路径如下: 即 根目录/dir0.js 根目录/path1/dir1.js 根目录/paht1/path2/dir2.js 每个d ...

  9. 检测固定IP的端口是否开放批出

    因为运维工作经常需要telnet某个IP的端口是否正常,因此有了下文 .BAT内容如下: @echo off for /f %%i in ('type ip.txt') do ( echo %%i t ...

  10. C#下Label的多行显示

    效果如图 1. tableLayout 三行两列 第一行 存放二维码的信息 第二行空白,用于分割 第三行存储LOGO信息 2. Lable4个,Dock属性都为Fill 第一列TextAlign使用M ...