题目描述

VRI(Voltron 机器人学会)的工程师建造了 n 个机器人。任意两个兼容的机 器人站在同一个格子时可以合并为一个复合机器人。

我们把机器人用 1 至 n 编号(n ≤ 9)。如果两个机器人的编号是连续的,那 么它们是兼容的,可以合并成一个复合机器人。最初这 n 个机器人各自都只有唯 一的编号。而一个由两个或以上的机器人合并构成的复合机器人拥有两个编号, 分别是构成它的所有机器人中最小和最大的编号。

例如,2 号机器人只可以与 1 号或 3 号机器人合并。若 2 号机器人与 3 号机 器人合并,可构成编号为 2-3 的复合机器人。如果编号为 2-3 的复合机器人与编 号为 4-6 的复合机器人合并,可构成编号为 2-6 的复合机器人。当所有机器人合 并以后则构成 1-n 复合机器人。

工程师把这 n 个机器人放在了一个封闭的房间中,房间四周均是墙。该房间 被划分成 w × h 个方格。有些方格有障碍物,机器人不可经过或停留;其余方格 允许多个机器人停留,同时允许机器人经过。任何时候一个机器人只占用一个方 格。初始时刻,所有机器人均在不同的方格中。

这些原始的机器人不会自发地移动。它们只有被工程师沿 x 轴或 y 轴推动 后,才会沿推动的方向不断向前直线移动,直至碰到障碍物或墙停止移动。停止 移动后,它会扫描当前的格子是否存在可以与它合并的机器人,如果有,则合并 并继续检查,直至不能再合并为止。工程师只能沿水平向左、水平向右、竖直向 上、竖直向下四个方向推动机器人,并且,在机器人尚未停止移动时,不允许推 动其它机器人,因此任何时刻,房间中都只能有一个机器人移动。

为了帮助机器人转向,工程师在一些格子中放置了转向器。具体地说,转向 器分为顺时针转向器(右转器)和逆时针转向器(左转器),顺时针转向器可以 使到达该格子的机器人沿顺时针方向转向 90°;逆时针转向器可以使到达该格 子的机器人沿逆时针方向转向 90°。

现在,我们将告诉你初始时刻房间内的信息。请你计算工程师最少共计需要 推动机器人多少次,才能把所有的 n 个机器人全部合并(如果可能的话)。

题解

这道题图的规模较大,但关键点树较少,容易让人想到斯坦纳树模型。

一般的斯坦纳树带着一个点集,但这道题机器人只能合并成一个区间,那么我们就记dp[i][j][k]表示一个区间为i~j的机器人在k点的最小步数。

然后我们预处理出一个点往四个方向走一步到达的点。

转移和斯坦纳树一样,先区间dp一下,在spfa转移。

细节

调死我了这题,首先预处理dfs时有可能出现环,所以我们要打visit,但是visit一定要记方向!!!!!

搞了个小优化,spfa转移的时候,先把所有点的dis从小到大排序,在按照顺序转移,于是成功的排到了洛谷rank倒三,bzoj直接TLE。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 0x3f3f3f3f
#define N 509
#define R register
using namespace std;
char s[N][N];
int dp[][][N*N],h,w,n,lef[],righ[],id[N][N],pp,tran[N*N][],p[N*N];
bool vis[N*N],vi[N*N][];
int h1,t1,q[N*N],ddf_a,ddf_b;
const int dx[]={,,,-};
const int dy[]={,-,,};
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline bool pd(int i,int j){return i<||j<||i>h||j>w||s[i][j]=='x';}
inline bool cmp(int a,int b){return dp[ddf_a][ddf_b][a]<dp[ddf_a][ddf_b][b];}
int dfs(int i,int j,int fx){
if(~tran[id[i][j]][fx])return tran[id[i][j]][fx];
if(vi[id[i][j]][fx])return ;
vi[id[i][j]][fx]=;
int xx=i+dx[fx],yy=j+dy[fx];
if(pd(xx,yy))return vi[id[i][j]][fx]=,tran[id[i][j]][fx]=id[i][j];
if(s[xx][yy]=='A'){
tran[id[i][j]][fx]=dfs(xx,yy,lef[fx]);
return vi[id[i][j]][fx]=,tran[id[i][j]][fx];
}
if(s[xx][yy]=='C'){
tran[id[i][j]][fx]=dfs(xx,yy,righ[fx]);
return vi[id[i][j]][fx]=,tran[id[i][j]][fx];
}
tran[id[i][j]][fx]=dfs(xx,yy,fx);
return vi[id[i][j]][fx]=,tran[id[i][j]][fx];
}
inline void spfa(int x,int y,int s){
q[h1=t1=]=s;
while(h1<=t1){
int u=q[h1++];vis[u]=;
for(R int i=;i<;++i){
int v=tran[u][i];if(v<=)continue;
if(dp[x][y][v]>dp[x][y][u]+){
dp[x][y][v]=dp[x][y][u]+;
if(!vis[v]){vis[v]=;q[++t1]=v;}
}
}
}
}
int main(){
lef[]=;lef[]=;lef[]=;lef[]=;
righ[]=;righ[]=;righ[]=;righ[]=;
n=rd();w=rd();h=rd();
memset(dp,0x3f,sizeof(dp));
memset(tran,-,sizeof(tran));
for(R int i=;i<=h;++i)scanf("%s",s[i]+);
for(R int i=;i<=h;++i)
for(R int j=;j<=w;++j)if(!pd(i,j)){
id[i][j]=++pp;
if(isdigit(s[i][j]))dp[s[i][j]^][s[i][j]^][pp]=;
}
for(R int i=;i<=h;++i)
for(R int j=;j<=w;++j)if(!pd(i,j)){
for(int k=;k<;++k){
tran[id[i][j]][k]=dfs(i,j,k);
}
}
for(R int i=;i<=pp;++i)p[i]=i;
for(R int len=;len<=n;++len)
for(R int i=;i+len-<=n;++i){
int j=i+len-;
for(R int k=;k<=pp;++k){
for(R int f=i;f<j;++f)dp[i][j][k]=min(dp[i][j][k],dp[i][f][k]+dp[f+][j][k]);
}
ddf_a=i;ddf_b=j;
sort(p+,p+pp+,cmp);
for(R int k=;k<=pp;++k)spfa(i,j,p[k]);
}
int ans=2e9;
for(R int i=;i<=pp;++i)ans=min(ans,dp[][n][i]);
if(ans==inf)puts("-1");else printf("%d",ans);
return ;
}

[APIO2013]机器人(斯坦纳树)的更多相关文章

  1. BZOJ 3205 [Apio2013]机器人 ——斯坦纳树

    腊鸡题目,实在卡不过去. (改了一下午) 就是裸的斯坦纳树的题目,一方面合并子集,另一方面SPFA迭代求解. 优化了许多地方,甚至基数排序都写了. 还是T到死,不打算改了,就这样吧 #include ...

  2. [BZOJ3205][APIO2013]Robot(斯坦纳树)

    3205: [Apio2013]机器人 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 1007  Solved: 240[Submit][Status ...

  3. [Bzoj3205][Apio2013]机器人(斯坦纳树)(bfs)

    3205: [Apio2013]机器人 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 977  Solved: 230[Submit][Status] ...

  4. [APIO2013]机器人[搜索、斯坦纳树]

    题意 题目链接 分析 记 g(d,x,y) 表示从 (x,y) 出发,方向为 d 到达的点,这个可以通过记忆化搜索求出,注意如果转移成环(此时向这个方向走没有意义)要特判. 记 f(l,r,x,y) ...

  5. bzoj 3205: [Apio2013]机器人【dfs+斯坦纳树+spfa】

    第一次听说斯坦纳树这种东西 先dfs预处理出来dis[i][j][k]表示格子(i,j)向k方向转移能到哪,记忆话搜索预处理,注意如果有环的话特判一下 设f[i][j][x][y]表示复合机器人i-j ...

  6. 【BZOJ2595】游览计划(状压DP,斯坦纳树)

    题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...

  7. HDU 4085 斯坦纳树

    题目大意: 给定无向图,让前k个点都能到达后k个点(保护地)中的一个,而且前k个点每个需要占据后k个中的一个,相互不冲突 找到实现这个条件达到的选择边的最小总权值 这里很容易看出,最后选到的边不保证整 ...

  8. hdu4085 Peach Blossom Spring 斯坦纳树,状态dp

    (1)集合中元素表示(1<<i), i从0开始 (2)注意dp[i][ss] = min(dp[i][ss], dp[i][rr | s[i]] + dp[i][(ss ^ rr) | s ...

  9. hdu 3311 斯坦纳树

    思路:虚拟一个0号节点,将每个点建一条到0号节点的边,权值为挖井需要的价值.并要保证0号节点同另外n个寺庙一样被选择即可. 然后就是求斯坦纳树了. #include<map> #inclu ...

随机推荐

  1. nmon for Linux & Java

    nmon for Linux | Main / HomePagehttp://nmon.sourceforge.net/pmwiki.php Java Nmon Analyser download | ...

  2. 练习MD5加密jar包编写

    简介 参数签名可以保证开发的者的信息被冒用后,信息不会被泄露和受损.原因在于接入者和提供者都会对每一次的接口访问进行签名和验证. 签名sign的方式是目前比较常用的方式. 第1步:接入者把需求访问的接 ...

  3. js-跨域源资源共享(CORS)

    ### 一. CORS(Cross-Origin Resource Sharing,跨域源资源共享) 基本思想:使用自定义HTTP头部让浏览器与服务器进行沟通 发送请求时,需附加一个Origin头部 ...

  4. artTemplate精彩文章(个人阅读过)

    轻量级artTemplate引擎 实现前后端分离—基础篇 :https://www.imooc.com/article/20263 轻量级artTemplate引擎 实现前后端分离—语法篇 : htt ...

  5. tomcat8.0部署启动

    http://tomcat.apache.org/download-80.cgi 打开命令行提示符窗口, 进入Tomcat安装目录, 进入bin目录下, 输入:service.bat install  ...

  6. 模仿jdk编译代码去除注释,多行注释

    package com.jachs.mvc; import java.*; import ch.qos.logback.classic.net.SyslogAppender; /**** * * @a ...

  7. 转《service worker在移动端H5项目的应用》

    1. PWA和Service Worker的关系 PWA (Progressive Web Apps) 不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技术将 Web App ...

  8. MySQL中KEY、PRIMARY KEY、UNIQUE KEY、INDEX 的区别

    参考:MySQL中KEY.PRIMARY KEY.UNIQUE KEY.INDEX 的区别 对于题目中提出的问题,可以拆分来一步步解决.在 MySQL 中 KEY 和 INDEX 是同义.那这个问题就 ...

  9. Python自动化测试之selenium从入门到精通

    1. 安装selenium 首先确保python安装成功,输入python -V 在windows下使用pip安装selenium,详情如图所示: 在ubuntu下使用pip install sele ...

  10. Lodop“对象不支持SET__LICENSES属性或方法”SET__LICENSES is not a function”

    Lodop中的方法如果书写错误,就会报错:“对象不支持XXX属性或方法”调试JS会报错”SET__LICENSES is not a function” LODOP.SET_LICENSES是加注册语 ...