BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*
BZOJ2595 Wc2008 游览计划
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]的范围内
斯坦纳树,状压DP记录路径
还有一点小小的不同,就是这道题用子集信息进行更新的时候我们需要减去当前点的权值一次,因为两个子集都包含了这个点,权值多算了一次
有关斯坦纳树的总结,请看https://www.cnblogs.com/dream-maker-yk/p/9676340.html
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 11
struct Node{int x,y,s;};
int mx[]={0,0,1,-1};
int my[]={1,-1,0,0};
int n,m,maxs;
int cost[N][N],st[N][N],vis[N][N],cnt;
int d[N][N][1<<N];
Node pre[N][N][1<<N];
bool in[N][N][1<<N];
queue<Node> Q;
void SPFA(){
while(!Q.empty()){
Node t=Q.front();Q.pop();
int x=t.x,y=t.y,s=t.s;
in[x][y][s]=0;
for(int i=0;i<4;i++){
int tx=x+mx[i],ty=y+my[i],ts=s|st[tx][ty];
if(tx<1||tx>n||ty<1||ty>m)continue;
if(d[tx][ty][ts]>d[x][y][s]+cost[tx][ty]){
d[tx][ty][ts]=d[x][y][s]+cost[tx][ty];
pre[tx][ty][ts]=t;
if(!in[tx][ty][ts]&&s==ts){
in[tx][ty][ts]=1;
Q.push((Node){tx,ty,ts});
}
}
}
}
}
void dfs(int x,int y,int s){
vis[x][y]=1;
Node t=pre[x][y][s];
int tx=t.x,ty=t.y,ts=t.s;
if(!tx&&!ty&&!ts)return;
dfs(tx,ty,ts);
if(x==tx&&y==ty)dfs(x,y,(s-ts)|st[x][y]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&cost[i][j]);
if(!cost[i][j])st[i][j]=1<<(cnt++);
}
maxs=(1<<cnt)-1;
memset(d,0x3f,sizeof(d));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(st[i][j])d[i][j][st[i][j]]=0;
for(int k=0;k<=maxs;k++){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(st[i][j]&&!(st[i][j]&k))continue;
for(int x=(k-1)&k;x;x=(x-1)&k){
int t=d[i][j][x|st[i][j]]+d[i][j][(k-x)|st[i][j]]-cost[i][j];
if(t<d[i][j][k]){
d[i][j][k]=t;
pre[i][j][k]=(Node){i,j,x|st[i][j]};
}
}
if(d[i][j][k]<INF){
Q.push((Node){i,j,k});
in[i][j][k]=1;
}
}
SPFA();
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)if(st[i][j]){
printf("%d\n",d[i][j][maxs]);
dfs(i,j,maxs);
for(int x=1;x<=n;x++){
for(int y=1;y<=m;y++){
if(st[x][y])putchar('x');
else if(vis[x][y])putchar('o');
else putchar('_');
}
putchar('\n');
}
return 0;
}
return 0;
}
BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*的更多相关文章
- BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)
Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 2030 Solved: 986[Submit][Status][ ...
- bzoj2595 [Wc2008]游览计划——斯坦纳树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...
- bzoj2595: [Wc2008]游览计划 斯坦纳树
斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况 我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有 转移方程: dp[ ...
- 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp
题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...
- 【BZOJ2595】[Wc2008]游览计划 斯坦纳树
[BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...
- Luogu 4294 [WC2008]游览计划 | 斯坦纳树
题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...
- 【BZOJ-2595】游览计划 斯坦纳树
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1518 Solved: 7 ...
- BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树
[题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...
- P4294 [WC2008]游览计划 (斯坦纳树)
题目链接 差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复. 题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了. #include<bi ...
- bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...
随机推荐
- Mysql建表好的例子
1. DROP TABLE IF EXISTS `sys_warehouse_area`;CREATE TABLE `sys_warehouse_area` ( `id` bigint(20) NOT ...
- 字体渲染技术(字体抗锯齿技术) -webkit-font-smoothing: antialiased;
1.-webkit-font-smoothing控制的字体渲染只对MacOS的webkit有效.所以,你在MacOS测试环境下面设置-webkit-font-smoothing时,只要你不把它设置为n ...
- ios 下拉刷新开源框架 MJRefresh
gitHub 下载框架 搜索MJExampleViewController.h 下拉刷新 MJTableViewController 上拉刷新 MJTableViewController Collec ...
- android项目1:打电话
android项目1:打电话 一.效果图 二.步骤 1.画好主界面 /call/res/layout/activity_main.xml <?xml version="1.0" ...
- 关于 MongoDB 复制集
为什么要使用复制集 1.备份数据通过自带的 mongo_dump/mongo_restore 工具也可以实现备份,但是毕竟没有复制集的自动同步备份方便. 2.故障自动转移部署了复制集,当主节点挂了后, ...
- Android6.0------权限申请RxPermissions
前面写了Android6.0权限介绍和权限单个,多个申请,用的是纯Java代码,本文主要说的是借助第三方库来实现权限申请. 借助第三方库 RxPermissions来申请6.0权限. RxPermis ...
- Hibernate入门_增删改查
一.Hibernate入门案例剖析: ①创建实体类Student 并重写toString方法 public class Student { private Integer sid; private ...
- grunt-init 默认模板目录更正
grunt-init是依赖grunt项目管理的脚手架工具,各种优点无须赘述,默认的template路径的作用:可以把自定义或其他模板放置其中,应用的时候直接调用模板名,不用每次寻找路径: 在安装gru ...
- linux FTP 操作
1.登陆: ftp 172.xxx.xxx.xxx 按提示输入用户名和密码 2.上传: 单个文件:put /路径/文件名 批量: 输入 prom 此命令是关闭交互(否则总是询问你是否要上传) 输入下载 ...
- Java类的finalize()方法
Java的Object类提供了一个finalize()方法,签名如下: protected void finalize() throws Throwable { } 该方法在JVM进行垃圾回收时之行, ...