Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge
Submit: 2030  Solved: 986
[Submit][Status][Discuss]

Description

Input

第一行有两个整数,N和 M,描述方块的数目。 
接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
行首行末也可能有多余的空格。

Output

由 N + 1行组成。第一行为一个整数,表示你所给出的方案
中安排的志愿者总数目。 
接下来 N行,每行M 个字符,描述方案中相应方块的情况: 
z  ‘_’(下划线)表示该方块没有安排志愿者; 
z  ‘o’(小写英文字母o)表示该方块安排了志愿者; 
z  ‘x’(小写英文字母x)表示该方块是一个景点; 
注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。

Sample Input

4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0

Sample Output

6
xoox
___o
___o
xoox

HINT

对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内

Source

 
很明显是斯坦纳树
$f[i][j][sta]$表示$(i,j)$这个位置,与其他景点的连通性为$sta$时的最小花费
转移的时候一种是枚举子集
另一种是spfa判断,
比较套路
 
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int limit = ;
const int INF = 1e9;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') {x = x * + c - ''; c = getchar();}
return x * f;
}
#define MP(i,j) make_pair(i,j)
#define se second
#define fi first
#define Pair pair<int,int>
int N, M, tot = ;
int a[][], f[][][limit];
int xx[] = {-, +, , };
int yy[] = {, , -, +};
int vis[][];
struct PRE {
int x, y, S;
}Pre[][][limit];
queue<Pair>q;
void SPFA(int cur) {
while(q.size() != ) {
Pair p = q.front();q.pop();
vis[p.fi][p.se] = ;
for(int i = ; i <; i++) {
int wx = p.fi + xx[i], wy = p.se + yy[i];
if(wx < || wx > N || wy < || wy > M) continue;
if(f[wx][wy][cur] > f[p.fi][p.se][cur] + a[wx][wy]) {
f[wx][wy][cur] = f[p.fi][p.se][cur] + a[wx][wy];
Pre[wx][wy][cur] = (PRE){p.fi, p.se, cur};
if(!vis[wx][wy])
vis[wx][wy] = , q.push(MP(wx,wy));
}
}
}
}
void dfs(int x, int y, int now) {
vis[x][y] = ;
PRE tmp = Pre[x][y][now];
if(tmp.x == && tmp.y == ) return;
dfs(tmp.x, tmp.y, tmp.S);
if(tmp.x == x && tmp.y == y) dfs(tmp.x, tmp.y, now - tmp.S);
}
int main() {
N = read(); M = read();
memset(f, 0x3f, sizeof(f));
for(int i = ; i <= N; i++)
for(int j = ; j <= M; j++) {
a[i][j] = read();
if(a[i][j] == )
f[i][j][ << tot] = , tot++;
}
int limit = ( << tot) - ;
for(int sta = ; sta <= limit; sta++) {
for(int i = ; i<= N; i++)
for(int j = ; j <= M;j++) {
for(int s = sta & (sta - ); s; s = (s - ) & sta) {
if(f[i][j][s] + f[i][j][sta - s] - a[i][j] < f[i][j][sta])
f[i][j][sta] = f[i][j][s] + f[i][j][sta - s] - a[i][j],
Pre[i][j][sta] = (PRE){i,j,s};
}
if(f[i][j][sta] < INF) q.push(MP(i,j)), vis[i][j] = ;
}
SPFA(sta);
}
int ansx, ansy, flag = ;
for(int i = ; i <= N && !flag; i++)
for(int j = ; j <= M; j++)
if(!a[i][j])
{ansx = i, ansy = j; flag = ; break;}
printf("%d\n",f[ansx][ansy][limit]);
memset(vis, , sizeof(vis));
dfs(ansx, ansy, limit);
for(int i = ; i <= N; i++, puts("")) {
for(int j = ; j <= M; j++) {
if(a[i][j] == ) putchar('x');
else if(vis[i][j]) putchar('o');
else putchar('_');
}
}
return ;
}

BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)的更多相关文章

  1. bzoj2595 [Wc2008]游览计划——斯坦纳树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...

  2. bzoj2595: [Wc2008]游览计划 斯坦纳树

    斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况 我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有 转移方程: dp[ ...

  3. 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...

  4. 【BZOJ2595】[Wc2008]游览计划 斯坦纳树

    [BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...

  5. Luogu 4294 [WC2008]游览计划 | 斯坦纳树

    题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...

  6. 【BZOJ-2595】游览计划 斯坦纳树

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

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

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

  8. P4294 [WC2008]游览计划 (斯坦纳树)

    题目链接 差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复. 题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了. #include<bi ...

  9. bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...

随机推荐

  1. android 常见分辨率(mdpi、hdpi 、xhdpi、xxhdpi )及屏幕适配

    1 Android手机目前常见的分辨率 1.1 手机常见分辨率: 4:3VGA     640*480 (Video Graphics Array)QVGA  320*240 (Quarter VGA ...

  2. 如何在首次启动 Linux 虚拟机时对其进行自定义

    在前面的教程中,你已学习如何通过 SSH 连接到虚拟机 (VM) 并手动安装 NGINX. 若要以快速一致的方式创建 VM,通常需要某种形式的自动化. 在首次启动 VM 时实现自定义的常见方法是使用  ...

  3. 创建和修改 ExpressRoute 线路的对等互连

    本文将指导你执行相关步骤,以便使用 Azure 门户和 Resource Manager 部署模型创建和管理 ExpressRoute 线路的路由配置. 配置先决条件 在开始配置之前,请务必查看先决条 ...

  4. 如何制作 Objective-C 的UML图 [2]

    如何制作 Objective-C 的UML图 [2] 说明 本教程旨在教你如何制作 Objective-C 的UML图,此为第二部分. 步骤 类继承关系 一个类符合某个协议 一个类认识另外一个对象(仅 ...

  5. Linode VPS主机套餐方案降低处理方法且不影响数据

    使用Linode VPS主机产品经历过512MB内存升级至1GB内存,再升级至2GB内存,以及目前推出1GB内存方案月付10美元.比如我们在使用Linode 2GB内存方案的时候占用资源不是太多,其实 ...

  6. Linux学习之路-2017/12/25

    三章  命令通配符 .PATH变量 支持多种文本的通配符 通配符                   含义 * 匹配零个或多个字符    ?   匹配任意单个字符 [0-9]   匹配范围内的数字 [ ...

  7. 铁乐学python_day01-和python有关的唠嗑

    铁乐学python_day01-和python有关的唠嗑 文:铁乐与猫 2018-03-16 01_python的历史 python的创始人为荷兰人吉多·范罗苏姆(Guido van Rossum). ...

  8. java开发初识

    jdk目录相关介绍: bin:存放的是java的相关开发工具 db:顾名思义jre附带的轻量级数据库 include:存放的是调用系统资源的接口文件 jre:java的运行环境 lib:核心的类库 s ...

  9. pandas高级操作总结

    1.pandas中的列的分位数 # 查看列的分位数 import pandas as pd # set columns type my_df['col'] = my_df['col'].astype( ...

  10. EntityFramework Core2.0 多对多关系配置

    ​ 在EF6.0 中,多对多关系配置时,系统会自动生成第三张表,来将两张有互相约束关系的表联系起来,但是在EF Core2.0中,我们需要手动建立第三张表,比如说有两个模型Passage.cs和Cat ...