BZOJ2595:[Wc2008]游览计划——题解(插头dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=2595
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 0Sample Output
6
xoox
___o
___o
xoox
参(抄)考(了):http://www.sigongzi.org/index.php/archives/jiyuliantongxingdezhuangtaiyasuodongtaiguihua.html
……原本也不想抄的啊,不然括号表达法还得学独立插头……
打眼一看就是一个插头dp,于是我们选用最小表示法求解。插头dp详见这里。
但是我们最开始学的插头dp只能解决哈密顿回路啊根本没有这道题这么复杂这可怎么办?
别慌,我们慢慢理:
1.显然景点是必须要取的(插头不能为“0”)。
2.显然路径必须是互相联通的线段。
对于1,我们强制不让这个格子不放插头即可。
对于2,我们考虑如果我们当前格子的上插头在轮廓线再没有与之相连通的插头,且同时我们已经扫完了所有景点,此时我们不选当前格子的话我们就将分开成两条路径了,所以必须要取;但是如果是左插头的话如果不取的话是可能符合2的。
然后正常插头dp即可。
(写这道题写了一天的我……)
(如果你插头dpA了这道题可以试一下这个数据):
4 3
0 1 1
10 10 1
10 10 0
10 10 1
ans:
3
xoo
__o
__x
___
#include<cstdio>
#include<cstring>
using namespace std;
const int INF=;
const int mod=;
const int N=;
const int M=;
struct node{//哈希表
int nxt;
int state,ans,pos,pre;//状态,答案,编号,前一个状态
bool choose;//是否选择该方块
}edge[M];
int head[mod+],cnt;
int lcnt,rcnt;
void insert(int now,int num,int ppos,int last,bool flag){
int u=now%mod;
for(int i=head[u];i;i=edge[i].nxt){
if(edge[i].state==now){
if(num<edge[i].ans){
edge[i].ans=num;
edge[i].pos=ppos;
edge[i].pre=last;
edge[i].choose=flag;
}
return;
}
}
edge[++cnt].nxt=head[u];
head[u]=cnt;
edge[cnt].state=now;
edge[cnt].ans=num;
edge[cnt].pos=ppos;
edge[cnt].pre=last;
edge[cnt].choose=flag;
return;
}
bool g[N][N];
int w[N],cntt;
int n,m,lastedge,e1,e2;
int mp[N][N];
int mapp[N];
inline void decode(int now){
for(int i=m;i>=;i--){
w[i]=now&;
now>>=;
}
return;
}
inline int encode(){
int x=,tot=;
memset(mapp,-,sizeof(mapp));
mapp[]=;
for(int i=;i<=m;i++){
if(mapp[w[i]]==-)mapp[w[i]]=++tot;
w[i]=mapp[w[i]];
x=x<<|w[i];
}
return x;
}
inline void init(){
memset(head,,sizeof(head));
lcnt=rcnt+;rcnt=cnt;
return;
}
inline void getans(){
for(int k=lcnt;k<=rcnt;k++){
int now=edge[k].state;
int num=edge[k].ans;
decode(now);
bool flag=;
for(int l=;l<=m&&flag;l++){
if(w[l]>)flag=;
}
if(num<cntt&&flag){
cntt=num;
lastedge=k;
}
}
return;
}
void plugdp(){
insert(,,,,);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
init();
if(i>e1||(i==e1&&j>e2))getans();//当前状态可能构成一种方案
for(int k=lcnt;k<=rcnt;k++){
int now=edge[k].state;
int num=edge[k].ans;
decode(now);
int is_right=w[j-];//这个格子左面格子的右插头
int is_down=w[j];//这个格子上面格子的下插头
bool flag=;//判断是否可以放插头,1可以不放
if(!mp[i][j])flag=;//景点必须放
else if(!is_down)flag=;//下插头不需要再匹配,故可以不放。
else{
flag=;
for(int l=;l<=m&&!flag;l++){
if(l!=j&&w[l]==is_down)flag=;
//上插头已经与轮廓线的一端匹配,可以在那一端延伸。
}
//没有匹配的插头,必须要接上
}
if(flag){//不放插头
w[j]=;//下插头没有用了
insert(encode(),num,(i-)*m+j,k,);
w[j]=is_down;
}
//放插头
if(!is_right&&!is_down)w[j]=;//一个新插头
else if(!is_down&&is_right)w[j]=is_right;//右插头延续过来
else if(is_right!=is_down&&is_right&&is_down){
for(int l=;l<=j;l++){//不太好说,但画个图应该就理解了
if(w[l]==is_right)w[l]=is_down;
}
}
//如果下插头和右插头匹配那么就把它们连起来
insert(encode(),num+mp[i][j],(i-)*m+j,k,);
}
}
}
init();
getans();
return;
}
void getans(int k){
if(!k)return;
int r=edge[k].pos;
int l=(r-)/m+;r=(r-)%m+;
g[l][r]=edge[k].choose;
getans(edge[k].pre);
return;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&mp[i][j]);
if(!mp[i][j])e1=i,e2=j;
}
}
cntt=INF;
plugdp();
printf("%d\n",cntt);
getans(lastedge);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(!mp[i][j])putchar('x');
else if(g[i][j])putchar('o');
else putchar('_');
}
putchar('\n');
}
return ;
}
BZOJ2595:[Wc2008]游览计划——题解(插头dp)的更多相关文章
- 斯坦纳树 [bzoj2595][wc2008]游览计划 题解
话说挺早就写过斯坦纳树了,不过当时没怎么总结,也不是很理解……现在来个小结吧~ 斯坦纳树就是包含给定点的最小生成树(个人理解权值应当为正). 一般来讲,给定点的数目应该很小吧...于是我们可以用状压D ...
- BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*
BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...
- [bzoj2595][WC2008]游览计划/[bzoj5180][Baltic2016]Cities_斯坦纳树
游览计划 bzoj-2595 wc-2008 题目大意:题目链接.题目连接. 注释:略. 想法:裸题求斯坦纳树. 斯坦纳树有两种转移方式,设$f[s][i]$表示联通状态为$s$,以$i$为根的最小代 ...
- [WC2008]游览计划(状压dp)
题面太鬼畜不粘了. 题意就是给一张n*m的网格图,每个点有点权,有k个关键点,让你把这k个关键点连成一个联通快的最小代价. 题解 这题nmk都非常小,解法肯定是状压,比较一般的解法插头dp,但不太好写 ...
- BZOJ2595 [Wc2008]游览计划 【状压dp + 最短路】
题目链接 BZOJ2595 题解 著名的斯坦纳树问题 设\(f[i][j][s]\)表示点\((i,j)\)与景点联通状况为\(s\)的最小志愿者数 设\(val[i][j]\)为\((i,j)\)需 ...
- BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)
Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 2030 Solved: 986[Submit][Status][ ...
- BZOJ2595[WC2008]游览计划
Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数 ...
- BZOJ2595 WC2008游览计划(斯坦纳树)
斯坦纳树板子题. 考虑状压dp,设f[i][j][S]表示当前在点(i,j)考虑转移,其所在的联通块包含的关键点集(至少)为S的答案. 转移时首先枚举子集,有f[i][j][S]=min{f[i][j ...
- luogu4294 [WC2008]游览计划(状压DP/斯坦纳树)
link 题目大意:给定一个网格图,有些点是关键点,选择格点有代价,求把所有关键点联通的最小代价 斯坦纳树模板题 斯坦纳树问题:给定一个图结构,有一些点是关键点,求把这些关键点联通的最小代价e 斯坦纳 ...
随机推荐
- java 通过内存映射文件来提高IO读取文件性能
MappedByteBuffer out = new RandomAccessFile("src/demo20/test.dat", "rw"). getCha ...
- 同一个电脑配置两个Git问题
拿到公司电脑后,正常配置gitlab,以及设置邮箱等等,可以使用公司邮箱,以及一系列设置 git config --global user.name "userName" git ...
- shell 判断日期间隔及润年
#!/bin/bash test.sh until echo "----------------------------------" echo "请输入您的选择:&qu ...
- 451. Swap Nodes in Pairs【LintCode java】
Description Given a linked list, swap every two adjacent nodes and return its head. Example Given 1- ...
- 【转】: 塞尔达组在GDC2017演讲的文字翻译:创新的勇气
大家好,我是藤林秀麿,以导演的身份参与<荒野之息>的制作,感谢大家的出席.我曾经作为设计者和导演制作了诸多塞尔达游戏(大地与时空之章.缩小帽.四支剑.幻影沙漏.天空之剑),回首望去,我已经 ...
- KETTLE并行
1.转换的并行 转换的并行是改变复制的数量 上面的转换相当于下面的: 实际是把一个任务拆成三部分执行,相当于在一个数据库连接中做了三次查询,数据库连接的开销没有增加,但是有三个进程一起执行. 2.jo ...
- 使用Node.js 搭建http服务器 http-server 模块
1. 安装 http-server 模块 npm install http-server -g 全局安装 2.在需要的文件夹 启动 http-server 默认的端口是8080 可以使 ...
- Fiber Network ZOJ 1967(Floyd+二进制状态压缩)
Description Several startup companies have decided to build a better Internet, called the "Fibe ...
- 2017年软件工程第八次作业-每周PSP例行报告
1.PSP表格 2.进度条 3.博文字数累积折线图 4.代码行数累积折线图 5.PSP饼图
- Android 7.1.1 又出幺蛾子了 —— 再谈 Android 上的 Wifi 连接
在之前的博客文章中,我写了点在 Android 6 系统中连接到指定名称的 Wifi 的体验.然而,在 Android 7 中,有一些东西又变化了.另外就是在那篇文章中我说要提供代码,结果拖到这篇文章 ...
.jpg)
