题意

\(n * m\)的网格,如果\(a_{i, j} = 0\)则表示景点,否则表示这里的需要的志愿者人数。求一种安排志愿者的方案使得所有景点连通且志愿者最少。

分析

本题可以插头dp,然而有一个东西叫斯坦纳树,来学习学习。

令\(f(i, j, s)\)表示\((i, j)\)为根,连通性为\(s\)的最少志愿者。则有转移:

$$
f(i, j, s) = min
\begin{cases}
f(i, j, t) + f(i, j, s-t) - a_{i, j} & t \neq \varnothing, t \subset s \\
f(i', j', s) & (i, j)与(i', j')相邻 \\
\end{cases}
$$

第一个转移可以直接做,然而第二个转移不是\(dag\)= =,所以我们得用最短路来求出来。

所以我们状压dp一下,然后每一个状态\(s\)先更新了第一种转移,然后再最短路一下。

然后完了= =

题解

如分析。

#include <bits/stdc++.h>
using namespace std;
const int N=10, M=N*N+5, oo=0x3f3f3f3f, dx[]={1, -1, 0, 0}, dy[]={0, 0, 1, -1};
int n, m, a[N][N], f[N][N][1<<N], p[N][N][1<<N], go[N][N], q[M], ta, fr, tot;
bool vis[N][N], ok[N][N];
void init() {
memset(f, 0x3f, sizeof f);
memset(p, -1, sizeof p);
scanf("%d%d", &n, &m);
for(int i=0; i<n; ++i) {
for(int j=0; j<m; ++j) {
scanf("%d", &a[i][j]);
if(!a[i][j]) {
f[i][j][go[i][j]=1<<tot++]=0;
}
}
}
}
inline int hash(const int x, const int y, const int s) {
return y+x*100+s*10000;
}
void spfa(int s) {
while(fr!=ta) {
int h=q[fr++], y=h%100, x=h/100;
fr=fr==M?0:fr;
for(int k=0; k<4; ++k) {
int fx=x+dx[k], fy=y+dy[k];
if(fx<0 || fx>=n || fy<0 || fy>=m) {
continue;
}
int temp=f[x][y][s]+a[fx][fy];
if(f[fx][fy][s]>temp) {
f[fx][fy][s]=temp;
if(!vis[fx][fy]) {
vis[fx][fy]=1;
q[ta++]=hash(fx, fy, 0);
ta=ta==M?0:ta;
}
p[fx][fy][s]=hash(x, y, s);
}
}
vis[x][y]=0;
}
fr=ta=0;
}
void work() {
int all=1<<tot;
for(int s=1; s<all; ++s) {
for(int i=0; i<n; ++i) {
for(int j=0; j<m; ++j) {
for(int t=s&(s-1); t; t=s&(t-1)) {
int temp=f[i][j][t]+f[i][j][s-t]-a[i][j];
if(f[i][j][s]>temp) {
f[i][j][s]=temp;
p[i][j][s]=hash(i, j, t);
}
}
if(f[i][j][s]!=oo) {
vis[i][j]=1;
q[ta++]=hash(i, j, 0);
}
}
}
spfa(s);
}
}
void dfs(int i, int j, int s) {
ok[i][j]=1;
int h=p[i][j][s];
if(h<0) {
return;
}
int y=h%100, x=(h%10000)/100, t=h/10000;
dfs(x, y, t);
if(i==x && j==y) {
dfs(x, y, s-t);
}
}
void out() {
for(int i=0; i<n; ++i) {
for(int j=0; j<m; ++j) {
if(go[i][j]) {
printf("%d\n", f[i][j][(1<<tot)-1]);
dfs(i, j, (1<<tot)-1);
return;
}
}
}
}
void prin() {
out();
for(int i=0; i<n; ++i) {
for(int j=0; j<m; ++j) {
if(go[i][j]) {
putchar('x');
}
else if(ok[i][j]) {
putchar('o');
}
else {
putchar('_');
}
}
puts("");
}
}
int main() {
init();
work();
prin();
return 0;
}

【BZOJ】2595: [Wc2008]游览计划的更多相关文章

  1. bzoj 2595 [Wc2008]游览计划(斯坦纳树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2595 [题意] 给定N*M的长方形,选最少权值和的格子使得要求的K个点连通. [科普] ...

  2. bzoj:2595: [Wc2008]游览计划

    Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数 ...

  3. BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】

    传送门 题意:略 论文 <SPFA算法的优化及应用> http://www.cnblogs.com/lazycal/p/bzoj-2595.html 本题的核心就是求斯坦纳树: Stein ...

  4. BZOJ.2595.[WC2008]游览计划(DP 斯坦纳树)

    题目链接 f[i][s]表示以i为根节点,当前关键点的连通状态为s(每个点是否已与i连通)时的最优解.i是枚举得到的根节点,有了根节点就容易DP了. 那么i为根节点时,其状态s的更新为 \(f[i][ ...

  5. BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树

    [题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...

  6. 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

    2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 1572  Solved: 7 ...

  7. 【LG4294】[WC2008]游览计划

    [LG4294][WC2008]游览计划 题面 洛谷 bzoj 题解 斯坦纳树板子题. 斯坦纳树的总结先留个坑. 代码 #include <iostream> #include <c ...

  8. BZOJ_2595_[Wc2008]游览计划_斯坦纳树

    BZOJ_2595_[Wc2008]游览计划_斯坦纳树 题意: 分析: 斯坦纳树裸题,有几个需要注意的地方 给出矩阵,不用自己建图,但枚举子集转移时会算两遍,需要减去当前点的权值 方案记录比较麻烦,两 ...

  9. [WC2008]游览计划 解题报告

    [WC2008]游览计划 斯坦纳树板子题,其实就是状压dp 令\(dp_{i,s}\)表示任意点\(i\)联通关键点集合\(s\)的最小代价 然后有转移 \[ dp_{i,S}=\min_{T\in ...

随机推荐

  1. Mysql中文乱码问题完美解决方案

    drop database`netctoss_demo` ;CREATE DATABASE `netctoss_demo` CHARACTER SET 'utf8' COLLATE 'utf8_gen ...

  2. Javascript事件冒泡机制

    1. 事件 在浏览器客户端应用平台,基本生都是以事件驱动的,即某个事件发生,然后做出相应的动作. 浏览器的事件表示的是某些事情发生的信号.事件的阐述不是本文的重点,尚未了解的朋友,可以访问W3scho ...

  3. SimpleHashTable

    简单的Hash Table 实现,下次被问到,至少不是从0开始.不过笔试问这个毕竟不多. public struct Item<K, V> { public K Key { get; se ...

  4. bbed的使用--安装及初探

    bbed是oracle内部一款用来直接查看和修改数据文件数据的工具,可以直接修改Oracle数据文件块的内容,在一些特殊恢复场景下比较有用. 1.bbed 的安装 在9i/10g中连接生成bbed: ...

  5. 关于Application Insights遥测功能使用【遇到问题】

    简介:Application Insights是微软发布的一个在线服务,可以监测自己的网站应用,进行性能管理以及使用分析. Application Insights功能一开始是出现在Visualstu ...

  6. GitHub上史上最全的Android开源项目分类汇总 (转)

    GitHub上史上最全的Android开源项目分类汇总 标签: github android 开源 | 发表时间:2014-11-23 23:00 | 作者:u013149325 分享到: 出处:ht ...

  7. hdu 1003 MAX SUM 简单的dp,测试样例之间输出空行

    测试样例之间输出空行,if(t>0) cout<<endl; 这样出最后一组测试样例之外,其它么每组测试样例之后都会输出一个空行. dp[i]表示以a[i]结尾的最大值,则:dp[i ...

  8. flv文件格式解析!!!

    flv头 FLV header 总体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag组成. Signature: FLV 文件的前3个字 ...

  9. JSON语法简介 介绍 json

    JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation),类似 XML,但比 XML 更小.更快,更易解析. 实例 { "employees ...

  10. java的几种连接池

    连接池的管理用了了享元模式,这里对连接池进行简单设计. 一.设计思路 1.连接池配置属性DBbean:里面存放可以配置的一些属性 2.连接池接口IConnectionPool:里面定义一些基本的获取连 ...