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 斯坦纳 ...
随机推荐
- replace与replaceAll的区别
这两者有些人很容易搞混,因此我在这里详细讲述下. replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了 ...
- python开发ftp服务器第一天(pyftpdlib)
学习了大约快一个月的python,现在开始有意识做一些项目.(我的新书<Python爬虫开发与项目实战>出版了,大家可以看一下样章) 据我了解,python现在更多的是用于自动化运维方面, ...
- moment.js使用方法总结
Moment.js是一个轻量级的JavaScript时间库,它方便了日常开发中对时间的操作,提高了开发效率.日常开发中,通常会对时间进行下面这几个操作:比如获取时间,设置时间,格式化时间,比较时间等等 ...
- python接口自动化1-发送get请求 前言
前言 requests模块,也就是老污龟,为啥叫它老污龟呢,因为这个官网上的logo就是这只污龟,接下来就是学习它了. 一.环境安装 1.用pip安装requests模块 >>pip in ...
- Phaser3让超级玛丽实现轻跳、高跳及加上对应的跳跃声音
mario jumper 在线测试地址:http://www.ifiero.com/uploads/phaserjs3/jumper/ 空格键:轻按:跳低 ,长按:跳高键盘:--> 向右 , ...
- PHASER3 设置场景SCENE SLEEPING休眠和WAKE唤醒
A good way to set scene stop when hidden and run while visible again ! 使用sleep和wake方法的好处: 1.可以彻底让sce ...
- java基础学习总结--开篇
春去秋来,转眼间,参加工作快2年了.本来应该是3年,然在毕业的第一年,有试着从事过其他行业.最终结果是失败了.2016年又回来从事软件开发,转眼即将2年,在这期间有许多收获,当然也有彷徨迷茫的时候,人 ...
- Spark之编程模型RDD
前言:Spark编程模型两个主要抽象,一个是弹性分布式数据集RDD,它是一种特殊集合,支持多种数据源,可支持并行计算,可缓存:另一个是两种共享变量,支持并行计算的广播变量和累加器. 1.RDD介绍 S ...
- day05 字典 dict
今日内容: 字典 成对的保存数据. 以key:value的形式保存 用{}表示,每一项内容都是key:value, 每项数据之间用逗号隔开 字典中的key是不能重复的. 存储是依靠着key来计算的. ...
- Paper Reading - Deep Captioning with Multimodal Recurrent Neural Networks ( m-RNN ) ( ICLR 2015 ) ★
Link of the Paper: https://arxiv.org/pdf/1412.6632.pdf Main Points: The authors propose a multimodal ...
.jpg)
