【BZOJ-2595】游览计划 斯坦纳树
2595: [Wc2008]游览计划
Time Limit: 10 Sec Memory Limit: 256 MBSec Special Judge
Submit: 1518 Solved: 714
[Submit][Status][Discuss]
Description
Input
第一行有两个整数,N和 M,描述方块的数目。
接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
行首行末也可能有多余的空格。
Output
由 N + 1行组成。第一行为一个整数,表示你所给出的方案中安排的志愿者总数目。
接下来 N行,每行M 个字符,描述方案中相应方块的情况:
z ‘_’(下划线)表示该方块没有安排志愿者;
z ‘o’(小写英文字母o)表示该方块安排了志愿者;
z ‘x’(小写英文字母x)表示该方块是一个景点;
注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。
Sample Input
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0
Sample Output
xoox
___o
___o
xoox
HINT
对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内
Source
Solution
现在就是留下板子走人= =
状压dp+spfa松弛一下就可以了。
自己写个破烂模板还要调一会= =,写完后发现网上绝大部分的人都是三个数压起来,只有我弱智的记下来。
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define INF 0xf0f0f0f
#define Pa pair<int,int>
#define PPa pair<Pa,int>
#define fi first
#define se second
#define MP make_pair Pa nidx[150];
PPa nidp[250000];
int N,S,M,mp[11][11],bin[11][11];
int idx[11][11],idp[11][11][1<<10],dp[11][11][1<<10],fr[11][11][1<<10]; inline void Update(int nx,int ny,int nz,int ox,int oy,int oz,int z)
{
if (dp[nx][ny][nz]>z) dp[nx][ny][nz]=z,fr[nx][ny][nz]=idp[ox][oy][oz];
} int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1},visit[150];
queue<int>q;
inline void Spfa(int sta)
{
while (!q.empty()) {
int now=q.front(); visit[now]=0; q.pop();
int x=nidx[now].fi,y=nidx[now].se;
for (int d=0; d<4; d++) {
int tx=x+dx[d],ty=y+dy[d];
if (!tx || !ty || tx>N || ty>M) continue;
if (dp[tx][ty][sta]>dp[x][y][sta]+mp[tx][ty]) {
Update(tx,ty,sta,x,y,sta,dp[x][y][sta]+mp[tx][ty]);
if (!visit[idx[tx][ty]])
q.push(idx[tx][ty]),visit[idx[tx][ty]]=1;
}
}
}
} bool mark[11][11];
inline void Dfs(int x,int y,int sta)
{
if (!fr[x][y][sta]) return;
mark[x][y]=1;
int now=fr[x][y][sta];
int tx=nidp[now].fi.fi,ty=nidp[now].fi.se,ts=nidp[now].se;
Dfs(tx,ty,ts);
if (tx==x && ty==y) Dfs(tx,ty,sta-ts);
} int main()
{
memset(dp,0xf,sizeof(dp));
scanf("%d%d",&N,&M);
for (int i=1; i<=N; i++)
for (int j=1; j<=M; j++) {
scanf("%d",&mp[i][j]);
if (!mp[i][j]) bin[i][j]=1<<(S++),dp[i][j][bin[i][j]]=0;
} for (int i=1,Idx=0,Idp=0; i<=N; i++)
for (int j=1; j<=M; j++) {
idx[i][j]=++Idx; nidx[Idx]=MP(i,j);
for (int k=0; k<(1<<S); k++)
idp[i][j][k]=++Idp,nidp[Idp]=MP(MP(i,j),k);
} for (int k=1; k<(1<<S); k++) {
for (int i=1; i<=N; i++) {
for (int j=1; j<=M; j++) {
for (int s=k&(k-1); s; s=(s-1)&k)
Update(i,j,k,i,j,s,dp[i][j][s]+dp[i][j][k-s]-mp[i][j]);
if (dp[i][j][k]!=INF)
q.push(idx[i][j]),visit[idx[i][j]]=1;
}
}
Spfa(k);
} for (int i=1; i<=N; i++) {
for (int j=1; j<=M; j++)
if (!mp[i][j]) {
printf("%d\n",dp[i][j][(1<<S)-1]);
Dfs(i,j,(1<<S)-1);
for (int x=1; x<=N; x++,puts(""))
for (int y=1; y<=M; y++) {
if (!mp[x][y]) printf("x");
else if (mark[x][y]) printf("o");
else printf("_");
}
return 0;
}
} return 0;
}
【BZOJ-2595】游览计划 斯坦纳树的更多相关文章
- BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树
[题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...
- 【BZOJ2595】[Wc2008]游览计划 斯坦纳树
[BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...
- Luogu 4294 [WC2008]游览计划 | 斯坦纳树
题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...
- bzoj2595: [Wc2008]游览计划 斯坦纳树
斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况 我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有 转移方程: dp[ ...
- bzoj2595 [Wc2008]游览计划——斯坦纳树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...
- BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)
Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 2030 Solved: 986[Submit][Status][ ...
- P4294 [WC2008]游览计划 (斯坦纳树)
题目链接 差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复. 题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了. #include<bi ...
- 洛谷4294 [WC2008]游览计划——斯坦纳树
题目:https://www.luogu.org/problemnew/show/P4294 大概是状压.两种转移,一个是以同一个点为中心,S由自己的子集拼起来:一个是S相同.中心不同的同层转移. 注 ...
- @bzoj - 2595@ 游览计划
目录 @description@ @solution@ @accepted code@ @details@ @description@ 从未来过绍兴的小D有幸参加了Winter Camp 2008,他 ...
随机推荐
- 那些年的 网络通信之 TCP/IP 传输控制协议 ip 加 端口 客户端上传文件到服务器端服务器端返回上传成功消息
多线程开启, 客户端通过 Socket 流 上传文件到服务端的一个小程序练习. 1. 抓住阻塞式方法,去调试 2. 获取对应流对象操作对应的对象 这时候自己不能懵,一定要清晰,最好命名就能区别,一搞混 ...
- WebSlides - 轻松制作漂亮的 HTML 幻灯片(演讲稿)
WebSlides 是一个开源的 HTML 幻灯片项目,能够帮助熟悉前端语言的开发者快速制作出效果精美的幻灯片.页面中的每个 <section> 都是一个独立的幻灯片,只需要很少的 CSS ...
- HDU 2056 龟兔赛跑 (DP)
题意:见题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2059 解题报告:以前一直没看出来这题是个DP题,知道是DP题就简单了 .首先要把起点和终点看成 ...
- Hive笔记之严格模式(strict mode)
Hive有一个严格模式,在严格模式下会对可能产生较大查询结果的语句做限制,禁止其提交执行. 一.切换严格模式 查看当前的模式: hive> set hive.mapred.mode; hive. ...
- bzoj 1432 数学(找规律)
我们可以发现所有的情况(除n=1时),都可以找到两个交叉的直线,就是第一层的那 两个线段所在的直线如图中左 那么我们以这个为准,两边对称着加直线,会得到右图,每一层是折线,且每 加一对儿就多两条线段, ...
- CSS Pseudo-classes
先来一条金科玉律: 伪类的效果可以通过添加一个实际的类来达到:伪元素的效果可以通过添加一个实际的元素来达到. 第一部分,Pseudo-classes,伪类 一.链接系 (这个应该是最熟悉的啦.) a: ...
- Linux输出重定向>和>>的区别是什么
[简介:>与>>的区别] 1 > 是定向输出到文件,如果文件不存在,就创建文件:如果文件存在,就将其清空:一般我们备份清理日志文件的时候,就是这种方法:先备份日志,再用`& ...
- BAT获取FTP指定文件
以下两个文件放在同一目录下 getfile.bat文件内容如下: @echo offftp.exe -i -s:getfile.txt 192.168.1.2(更换成你的ip,参数之间有空格)paus ...
- Linux中Samba详细安装【转】
转自:http://www.cnblogs.com/whiteyun/archive/2011/05/27/2059670.html 为了实现Windows主机与Linux服务器之间的资源共享,Lin ...
- 树莓派编译安装opencv3 (2019.1.6更新)
一.更新系统 sudo apt-get update sudo apt-get upgrade sudo rpi-update #重启系统 sudo reboot 二.安装依赖库及程序 sudo ap ...