题目描述

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[10][10][N*N],h,w,n,lef[5],righ[5],id[N][N],pp,tran[N*N][4],p[N*N];
bool vis[N*N],vi[N*N][4];
int h1,t1,q[N*N],ddf_a,ddf_b;
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};
inline int rd(){int x=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x;
}
inline bool pd(int i,int j){return i<1||j<1||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 0;vi[id[i][j]][fx]=1;int xx=i+dx[fx],yy=j+dy[fx];    if(pd(xx,yy))return vi[id[i][j]][fx]=0,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]=0,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]=0,tran[id[i][j]][fx];}tran[id[i][j]][fx]=dfs(xx,yy,fx);return vi[id[i][j]][fx]=0,tran[id[i][j]][fx];
}
inline void spfa(int x,int y,int s){q[h1=t1=1]=s;while(h1<=t1){int u=q[h1++];vis[u]=0;for(R int i=0;i<4;++i){int v=tran[u][i];if(v<=0)continue;if(dp[x][y][v]>dp[x][y][u]+1){dp[x][y][v]=dp[x][y][u]+1;if(!vis[v]){vis[v]=1;q[++t1]=v;}}} }
}
int main(){lef[0]=3;lef[3]=1;lef[1]=2;lef[2]=0;righ[0]=2;righ[2]=1;righ[1]=3;righ[3]=0;n=rd();w=rd();h=rd();memset(dp,0x3f,sizeof(dp));memset(tran,-1,sizeof(tran));for(R int i=1;i<=h;++i)scanf("%s",s[i]+1);for(R int i=1;i<=h;++i)for(R int j=1;j<=w;++j)if(!pd(i,j)){id[i][j]=++pp;if(isdigit(s[i][j]))dp[s[i][j]^48][s[i][j]^48][pp]=0;}for(R int i=1;i<=h;++i)for(R int j=1;j<=w;++j)if(!pd(i,j)){for(int k=0;k<4;++k){tran[id[i][j]][k]=dfs(i,j,k);}}for(R int i=1;i<=pp;++i)p[i]=i;for(R int len=1;len<=n;++len)for(R int i=1;i+len-1<=n;++i){int j=i+len-1;for(R int k=1;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+1][j][k]); }ddf_a=i;ddf_b=j;sort(p+1,p+pp+1,cmp);for(R int k=1;k<=pp;++k)spfa(i,j,p[k]);}int ans=2e9;for(R int i=1;i<=pp;++i)ans=min(ans,dp[1][n][i]);if(ans==inf)puts("-1");else printf("%d",ans);return 0;
} 

转载于:https://www.cnblogs.com/ZH-comld/p/10235848.html

[APIO2013]机器人(斯坦纳树)相关推荐

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

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

  2. bzoj1402 Ticket to Ride 斯坦纳树 + 状压dp

    给定\(n\)个点,\(m\)条边的带权无向图 选出一些边,使得\(4\)对点之间可达,询问权值最小为多少 \(n \leqslant 30, m \leqslant 1000\) 首先看数据范围,\ ...

  3. BZOJ 4006 Luogu P3264 [JLOI2015]管道连接 (斯坦纳树、状压DP)

    题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4006 (luogu)https://www.luogu.org/probl ...

  4. [WC2008]游览计划(斯坦纳树)

    [Luogu4294] 题解 : 斯坦纳树 \(dp[i][j]\) 表示以\(i\)号节点为根,当前状态为\(j\)(与\(i\)连通的点为\(1\)) 当根\(i\)不改变时状态转移方程是: \( ...

  5. 业界萌新对斯坦纳树的小结

    业界萌新对斯坦纳树的小结 0.简介 斯坦纳树问题是组合优化问题,与最小生成树相似,是最短网络的一种.最小生成树是在给定的点集和边中寻求最短网络使所有点连通.而最小斯坦纳树允许在给定点外增加额外的点,使 ...

  6. [bzoj4006][JLOI2015]管道连接_斯坦纳树_状压dp

    管道连接 bzoj-4006 JLOI-2015 题目大意:给定一张$n$个节点$m$条边的带边权无向图.并且给定$p$个重要节点,每个重要节点都有一个颜色.求一个边权和最小的边集使得颜色相同的重要节 ...

  7. 【BZOJ4774】修路 [斯坦纳树]

    修路 Time Limit: 20 Sec  Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 5 5 2 ...

  8. bzoj 4006 管道连接 —— 斯坦纳树+状压DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 用斯坦纳树求出所有关键点的各种连通情况的代价,把这个作为状压(压的是集合选择情况)的初 ...

  9. 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

    2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge Submit: 1572  Solved:  ...

最新文章

  1. 程序员都痛恨开会?多开 1 个会,我少写 1000 行代码......
  2. 怎么找到项目中所有同名的类_26岁转行程序员的成长历程--Day03从内存层面理解类和对象...
  3. php 调用继承的方法吗,如何从继承的方法中调用PHP父方法?
  4. GMaps.js - 轻松集成Google Maps的jQuery插件
  5. 【Excel-2010】VLOOKUP函数
  6. bzoj3435 [Wc2014]紫荆花之恋
  7. 编译原理实验五:编译器自动生成工具
  8. Windows 10系统安装AutoCAD 2007
  9. 教师在家长群内表扬配合家长的话术
  10. 小程序设置整个页面的背景颜色
  11. ReadProcessMemory()
  12. Linux bash命令入门
  13. 二叉树的最大深度(力扣作业)
  14. 基于单片机的空气检测系统的设计
  15. Python_Task06:函数与Lambda表达式
  16. 如何进入训练模式_健身计划非常重要,对于健身小白,新手期和成长期该如何制定?...
  17. 基于QT的滴滴网约车订单数据可视化分析
  18. windows10更新服务器修改,修改win10更新服务器地址
  19. xxl-job使用说明文档
  20. 游标cursor,游标循环和记录变量的定义

热门文章

  1. 51单片机4位数乘法C语言,51单片机实现4位数以内的加减法
  2. python filecmp
  3. 前端-requests-flask对应关系 HTTPTokenAuth
  4. java junit
  5. Linux多进程的应用
  6. html模拟word目录,word临时文件目录
  7. 浅谈数据库发展史和 OceanBase 的诞生
  8. excel文件占用空间大 xls xlsx等文件
  9. centos 更改root用户名(超简单)
  10. 消息中间件学习总结(21)——RocketMQ 消息丢失场景分析及如何解决!