[WC2008]游览计划 「斯坦那树模板」
斯坦那树
百度释义
斯坦纳树问题是组合优化问题,与最小生成树相似,是最短网络的一种。最小生成树是在给定的点集和边中寻求最短网络使所有点连通。而最小斯坦纳树允许在给定点外增加额外的点,使生成的最短网络开销最小。
即最小斯坦那树即为并非选择所有的结点,而是选择一部分结点,为保证它们连通,且求解最小开销
题解
斯坦那树模板
发现直接表示点的存在性没有意义
设函数 \(f[i][state]\) 表示:对于点 \(i\),其它结点与其连通情况
那么有两种转移
其一、由其子集转移
\]
之所以要减去 \(value_i\) 是因为会算重
附:枚举子集的方法
for (int sub = state & (state - 1); sub; sub = (sub - 1) & state)
其二、由相邻当前状态下结点转移
\]
发现很像三角形不等式,故考虑 \(SPFA\) 转移
总复杂度 \(O (n3^n + kE2^n)\),\(3^n\) 为枚举子集总复杂度
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = 10 + 5;
const int MAXM = 1 << 10;
const int INF = 0x3f3f3f3f;
const int NextX[4]= {- 1, 0, 0, 1}, NextY[4]= {0, - 1, 1, 0};
int N, M;
int Map[MAXN][MAXN]= {0};
struct preSt {
int x, y;
int state;
preSt (int fx = 0, int fy = 0, int fs = 0) :
x (fx), y (fy), state (fs) {}
} ;
int f[MAXN][MAXN][MAXM];
preSt pre[MAXN][MAXN][MAXM];
int cnt = 0;
queue<pair<int, int> > que;
void SPFA (int state) {
while (! que.empty()) {
pair<int, int> top = que.front();
que.pop();
int x = top.first, y = top.second;
for (int i = 0; i < 4; i ++) {
int tx = x + NextX[i];
int ty = y + NextY[i];
if (tx < 1 || tx > N || ty < 1 || ty > M)
continue;
if (f[x][y][state] + Map[tx][ty] < f[tx][ty][state]) {
f[tx][ty][state] = f[x][y][state] + Map[tx][ty];
pre[tx][ty][state] = preSt (x, y, state);
que.push(make_pair (tx, ty));
}
}
}
}
int tag[MAXN][MAXN]= {0};
void traceback (int x, int y, int state) {
if (! x || ! y)
return ;
tag[x][y] = 1;
preSt pr = pre[x][y][state];
traceback (pr.x, pr.y, pr.state);
if (pr.x == x && pr.y == y)
traceback (pr.x, pr.y, state - pr.state);
}
int getnum () {
int num = 0;
char ch = getchar ();
while (! isdigit (ch))
ch = getchar ();
while (isdigit (ch))
num = (num << 3) + (num << 1) + ch - '0', ch = getchar ();
return num;
}
int main () {
memset (f, 0x3f, sizeof (f));
N = getnum (), M = getnum ();
int px, py;
for (int i = 1; i <= N; i ++)
for (int j = 1; j <= M; j ++) {
Map[i][j] = getnum ();
if (! Map[i][j]) {
cnt ++, f[i][j][1 << (cnt - 1)] = 0;
px = i, py = j;
}
}
int limit = (1 << cnt) - 1;
for (int state = 1; state <= limit; state ++) {
for (int i = 1; i <= N; i ++)
for (int j = 1; j <= M; j ++) {
for (int sub = state & (state - 1); sub; sub = (sub - 1) & state) // from subset
if (f[i][j][sub] + f[i][j][state - sub] - Map[i][j] < f[i][j][state]) {
f[i][j][state] = f[i][j][sub] + f[i][j][state - sub] - Map[i][j];
pre[i][j][state] = preSt (i, j, sub);
}
if (f[i][j][state] < INF)
que.push(make_pair (i, j));
}
SPFA (state); // from other nodes
}
traceback (px, py, limit);
printf ("%d\n", f[px][py][limit]);
for (int i = 1; i <= N; i ++) {
for (int j = 1; j <= M; j ++) {
if (! Map[i][j])
putchar ('x');
else {
tag[i][j] ? putchar ('o') : putchar ('_');
}
}
puts ("");
}
return 0;
}
/*
4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0
*/
[WC2008]游览计划 「斯坦那树模板」的更多相关文章
- BZOJ_2595_[Wc2008]游览计划_斯坦纳树
BZOJ_2595_[Wc2008]游览计划_斯坦纳树 题意: 分析: 斯坦纳树裸题,有几个需要注意的地方 给出矩阵,不用自己建图,但枚举子集转移时会算两遍,需要减去当前点的权值 方案记录比较麻烦,两 ...
- BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*
BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...
- 【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)
上个月写的题qwq--突然想写篇博客 题目: 洛谷4294 分析: 斯坦纳树模板题. 简单来说,斯坦纳树问题就是给定一张有边权(或点权)的无向图,要求选若干条边使图中一些选定的点连通(可以经过其他点) ...
- bzoj 2595 [Wc2008]游览计划(斯坦纳树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2595 [题意] 给定N*M的长方形,选最少权值和的格子使得要求的K个点连通. [科普] ...
- BZOJ2595 WC2008游览计划(斯坦纳树)
斯坦纳树板子题. 考虑状压dp,设f[i][j][S]表示当前在点(i,j)考虑转移,其所在的联通块包含的关键点集(至少)为S的答案. 转移时首先枚举子集,有f[i][j][S]=min{f[i][j ...
- [WC2008]游览计划(斯坦纳树)
[Luogu4294] 题解 : 斯坦纳树 \(dp[i][j]\) 表示以\(i\)号节点为根,当前状态为\(j\)(与\(i\)连通的点为\(1\)) 当根\(i\)不改变时状态转移方程是: \( ...
- BZOJ.2595.[WC2008]游览计划(DP 斯坦纳树)
题目链接 f[i][s]表示以i为根节点,当前关键点的连通状态为s(每个点是否已与i连通)时的最优解.i是枚举得到的根节点,有了根节点就容易DP了. 那么i为根节点时,其状态s的更新为 \(f[i][ ...
- 【BZOJ2595】[Wc2008]游览计划 斯坦纳树
[BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...
- 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1572 Solved: 7 ...
随机推荐
- java之JDBC学习总结
以前一直以为jdbc是很高大上的东西,没想到今天学了jdbc,惊喜来了,just a tool!当然工具是用来帮助人们学习和提供方便的,所以总结了一下,也就是简单的三板斧: first :加载驱动 t ...
- jvm垃圾回收机制和常见算法
这是朋友给的面试题里边的,具体地址已经找不到,只能对原作者说声抱歉了: 理论上来讲sun公司只定义了垃圾回收机制规则,而步局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同. GC(Gar ...
- ElasticSearch搜索实例含高亮显示及搜索的特殊字符过滤
应用说明见代码注解. 1.简单搜索实例展示: public void search() throws IOException { // 自定义集群结点名称 String clusterName = & ...
- SpringBoot 6.SpringBoot使用 Log4j2 实现日志输出
一.添加 Log4j2 的依赖 <!-- 引入 log4j2 必须排除 logging --> <dependency> <groupId>org.springfr ...
- 实体框架自定义代码优先约定(EF6以后)
仅限EF6仅向前 - 此页面中讨论的功能,API等在实体框架6中引入.如果您使用的是早期版本,则部分或全部信息不适用. 使用Code First时,您的模型是使用一组约定从您的类计算的.默认的Code ...
- c#public、private、protected、internal、protected internal
public 公有访问.不受任何限制.private 私有访问.只限于本类成员访问,子类,实例都不能访问.protected 保护访问.只限于本类和子类访问,实例不能访问.internal 内部访问. ...
- Ubuntu 16.04搭建LAMP开发环境
基本设置 1.配置网络环境 管理员给分配了一个静态IP,所以还需要进一步配置网络环境 配置DNS:右上角网络连接->编辑链接->有线连接1->IPv4设置->DNS服务器:20 ...
- hdu 6301 Distinct Values (2018 Multi-University Training Contest 1 1004)
Distinct Values Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- 异步查询json传日期格式到前台,变成了时间戳的格式
问题: 使用mybatis 查询mysql数据库,其中一个日期格式的字段,由异步查询使用 json传递到前台,变成了时间戳,而不是日期格式了.如何使查询出的日期展示成日期格式呢 解决办法: 1.尝试使 ...
- BZOJ 百题纪念!
一百题辣! 现在NOI知识点中最基础的那部分已经学完了--这几天发现自己会写SA啊树剖啊可持久化Trie啊之类模板题--还挺开心的-- 逛了两天学长博客之后--BZOJ100题辣--也挺开心的-- 现 ...