luogu4294 [WC2008]游览计划(状压DP/斯坦纳树)
题目大意:给定一个网格图,有些点是关键点,选择格点有代价,求把所有关键点联通的最小代价
斯坦纳树模板题
斯坦纳树问题:给定一个图结构,有一些点是关键点,求把这些关键点联通的最小代价e
斯坦纳树问题其实是最小生成树MST问题的扩展
考虑状压DP,设f[x][s]
代表当前以x为根的树,关键点选取状态集合为s时的最小代价
考虑s由两个子集s1和s2转移过来,则DP方程为f[x][s]=f[x][s1]+f[x][s2]
。如果是点权,去重还要减去val[x]
。
考虑s由其它点转移过来,那么就枚举其它点,f[x][s]=f[y][s]+val[x][y]
,发现这其实就是最短路的转移形式,我们一开始把所有f<inf的点扔队列里跑spfa就行了
初始化:对于关键点x,有f[x][只包含x的集合]
=0,其它为inf
最后输出的答案即为f[某个关键点][(1<<tot)-1]
瞎写的板子:
for (int s = 1; s < (1 << tot); s++)
{
for (int i = 1; i <= n; i++)
{
for (s1 + s2 == s)
{
chkmin(f[i][s], f[i][s1]+f[i][s2]);
if (f[i][s] < inf) q.push(i), vis[i] = true;
}
}
while (!q.empty())
{
int x = q.front(); q.pop(), vis[x] = false;
for (int i : out[x]) if (f[x][s] + dis[x][i] < f[i][s])
{
f[i][s] = f[x][s] + dis[x][i];
if (vis[i] == false) vis[i] = true, q.push(i);
}
}
}
本题题解:
直接套用板子即可。
由于还要输出方案,我们维护一个pre,记录这个状态从哪个状态转移过来的,dfs一遍就行了。
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
struct data { int x, y, s; } pre[15][15][1050];
int n, m, tot, mp[15][15], f[15][15][1050], ex, ey;
bool vis[15][15], ans[15][15];
void dfs(int x, int y, int s)
{
if (pre[x][y][s].s == 0) return;
ans[x][y] = true;
dfs(pre[x][y][s].x, pre[x][y][s].y, pre[x][y][s].s);
if (pre[x][y][s].x == x && pre[x][y][s].y == y) dfs(pre[x][y][s].x, pre[x][y][s].y, pre[x][y][s].s ^ s);
}
int main()
{
scanf("%d%d", &n, &m); memset(f, 0x3f, sizeof(f));
for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++)
{
scanf("%d", &mp[i][j]);
if (mp[i][j] == 0) f[i][j][1 << (tot++)] = 0, ex = i, ey = j;
}
for (int s = 1; s < (1 << tot); s++)
{
queue<int> qx, qy;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
for (int s1 = s; s1 > 0; s1 = (s1 - 1) & s)
{
int s2 = s1 ^ s;
if (f[i][j][s] > f[i][j][s1] + f[i][j][s2] - mp[i][j])
{
f[i][j][s] = f[i][j][s1] + f[i][j][s2] - mp[i][j];
pre[i][j][s] = (data){i, j, s1};
}
}
if (vis[i][j] == false && f[i][j][s] != 0x3f3f3f3f) qx.push(i), qy.push(j), vis[i][j] = true;
}
}
while (!qx.empty())
{
int x = qx.front(), y = qy.front(); qx.pop(), qy.pop(); vis[x][y] = false;
for (int d = 0; d < 4; d++)
{
int nx = x + dx[d], ny = y + dy[d];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m)
{
if (f[nx][ny][s] > f[x][y][s] + mp[nx][ny])
{
f[nx][ny][s] = f[x][y][s] + mp[nx][ny];
pre[nx][ny][s] = (data){x, y, s};
if (vis[nx][ny] == false) vis[nx][ny] = true, qx.push(nx), qy.push(ny);
}
}
}
}
}
printf("%d\n", f[ex][ey][(1 << tot) - 1]);
dfs(ex, ey, (1 << tot) - 1);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
if (mp[i][j] == 0) printf("x");
else if (ans[i][j]) printf("o");
else printf("_");
printf("\n");
}
return 0;
}
luogu4294 [WC2008]游览计划(状压DP/斯坦纳树)的更多相关文章
- [WC2008]游览计划 状压DP,斯坦纳树
---题面--- 题解: 这是一道斯坦纳树的题,用状压+spfa来解决 什么是斯坦纳树? 一开始还以为是数据结构来着,其实跟最小生成树很像,大致就是最小生成树只能在各个点之间直接相连,而斯坦纳树则允许 ...
- [WC2008]游览计划(状压dp)
题面太鬼畜不粘了. 题意就是给一张n*m的网格图,每个点有点权,有k个关键点,让你把这k个关键点连成一个联通快的最小代价. 题解 这题nmk都非常小,解法肯定是状压,比较一般的解法插头dp,但不太好写 ...
- [bzoj2595][WC2008]游览计划/[bzoj5180][Baltic2016]Cities_斯坦纳树
游览计划 bzoj-2595 wc-2008 题目大意:题目链接.题目连接. 注释:略. 想法:裸题求斯坦纳树. 斯坦纳树有两种转移方式,设$f[s][i]$表示联通状态为$s$,以$i$为根的最小代 ...
- [BZOJ4006][JLOI2015]管道连接 状压dp+斯坦纳树
4006: [JLOI2015]管道连接 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1020 Solved: 552[Submit][Statu ...
- 动态规划:状压DP-斯坦纳树
最小生成树是最小斯坦纳树的一种特殊情况 最小生成树是在给定的点集和边中寻求最短网络使所有点连通 而最小斯坦纳树允许在给定点外增加额外的点,使生成的最短网络开销最小 BZOJ2595 题意是给定一个棋盘 ...
- BZOJ.2595.[WC2008]游览计划(DP 斯坦纳树)
题目链接 f[i][s]表示以i为根节点,当前关键点的连通状态为s(每个点是否已与i连通)时的最优解.i是枚举得到的根节点,有了根节点就容易DP了. 那么i为根节点时,其状态s的更新为 \(f[i][ ...
- 【状压dp】Trie 树 @中山纪念中学20170304
目录 Trie 树 PROBLEM 题目描述 输入 输出 样例输入 样例输出 SOLUTION CODE Trie 树 PROBLEM 题目描述 字母(Trie)树是一个表示一个字符串集合中所有字符串 ...
- HDU.3311.Dig The Wells(DP 斯坦纳树)
题目链接 \(Description\) 有n座庙.一共n+m个点,可以在任意一些点修建水井,不同位置花费不同:也可以某些点之间连无向边共享水.求使n座庙都有水的最小花费. \(Solution\) ...
- 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1572 Solved: 7 ...
随机推荐
- NSArray & NSDictionary
一.NSArray 1.1 简单创建方法由难到简 NSArray *arr = [[NSArray alloc] init]; NSArray *arr = [NSArray arrayWithObj ...
- 191. Number of 1 Bits 二进制中1的个数
[抄题]: Write a function that takes an unsigned integer and returns the number of ’1' bits it has (als ...
- spring4-1-Spring的简单介绍
Spring4.0 是 Spring 推出的一个重大版本升级,进一步加强了 Sring 作为 Java 领域第一开源平台的地位.Spring4.0 引入了众多 Java 开发者期盼的新特性,如泛型依赖 ...
- eclipse基础环境配置和svn、maven的配置以及maven的安装
安装eclipse和基础配置 第一步:解压eclipse安装包,直接解压就可以,绿色版安装 第二步:启动eclipse,注意这里的eclipse需要依赖jdk,并且版本需要匹配,否则启动会出 现问题. ...
- code1796 社交网络
输入描述 Input Description 输入文件中第一行有两个整数,n 和 m,表示社交网络中结点和无向边的数 目.在无向图中,我们将所有结点从 1 到 n 进行编号. 接下来 m 行,每行用三 ...
- 搭建自己的MQTT服务器
搭建自己的MQTT服务器 物联网电子世界 百家号08-2903:04 MQTT协议是广泛应用的物联网协议,使用测试MQTT协议需要MQTT的代理.有两种方法使用MQTT服务,一是租用现成的MQTT服务 ...
- OSAL的原理
讲解协议栈怎么运行起来!!回顾:1.应用层是一个任务,它有一个系统分配给他的数值唯一的编号叫做任务ID 2.任务可以处理事件,处理事件的这些代码都在一个函数里,这个函数叫任务事件处理函数 3.应用层任 ...
- Go 网络编程笔记
前言: 本文是学习<<go语言程序设计>> -- 清华大学出版社(王鹏 编著) 的2014年1月第一版 做的一些笔记 , 如有侵权, 请告知笔者, 将在24小时内删除, 转载请 ...
- 启动Hadoop HDFS时的“Incompatible clusterIDs”错误原因分析
"Incompatible clusterIDs"的错误原因是在执行"hdfs namenode -format"之前,没有清空DataNode节点的data目 ...
- SurfaceView实时绘图,视频流