3205: [Apio2013]机器人

Time Limit: 15 Sec  Memory Limit: 128 MB
Submit: 525  Solved: 131
[Submit][Status][Discuss]

Description

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个机器人全部合并(如果可能的话)。

Input

你的程序必须从标准输入读入。输入的第 1行包含 3个整数 n、w和 h,用空格隔开。输入文件中接下来的 h行描述初始时刻房间内的信息,每行包含w个字符。这w* h 字符中每一个表示房间中的一个格子,意义如下:
 
‘ 1’至‘9’:表示该方格中有一个机器人,编号为这个数字;
‘ x’:表示该方格有障碍物;
 
‘ A’:表示该方格中有一个逆时针转向器;
 
‘ C’:表示该方格中有一个顺时针转向器;
‘ .’:表示该方格为空地。

Output

你的程序必须输出到标准输出。输出仅一个整数,表示最少需要推动的次数。
若不能使所有机器人全部合并,输出-1。

Sample Input

4 10 5
1.........
AA...x4...
..A..x....
2....x....
..C.3.A...

Sample Output

5

HINT

第一步:向右推动 3 号机器人,当它碰到转向器后会向上继续移动,直至碰到墙壁停止移动。第二步:向上推动 4 号机器人,当它碰到墙壁后停止移动,与3 号机器人合并,构成  3-4 号机器人 第三步:向上推动 2 号机器人,当它碰到转向器后会向左移动,由于左侧为墙壁,故停留在原地。第四步:向右推动  2 号机器人,由于它在一个转向器上,故它会向上移动,直至碰到墙壁停止移动,与  1 号机器人合并,构成 1-2 号机器人。第五步:向左推动  3-4 号机器人,当它碰到墙壁后停止移动,与 1-2 号机器人合并,构成  1-4 号机器人。

n ≤ 9,≤ 500 且   h ≤ 500

Source

[Submit][Status][Discuss]
斯坦纳树 f[l][r][i][j]:已经将[l,r]的机器人合并,以(i,j)为根,最少步数 方程显然
注意一些优化: 1.图中有环需要特判 2.裸的SPFA会TLE
对于边权全部为1,有多个源点的SPFA可以采用如下形式降低复杂度为线性 先将所有源点按照初始值排序,放入队列1 每次取出队列1、队列2的队头,用少的去松弛,新点如队列2
f[l][r][i][j]寻址速度快于f[i][j][l][r]

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;struct Point{int x,y;Point(){}Point(int x,int y): x(x),y(y){}
};const int maxn = 501;
const int dx[4] = {1,0,-1,0};
const int dy[4] = {0,1,0,-1};
const int INF = 1E9;int n,m,t,cnt,tot,tail,f[10][10][maxn][maxn],Nex[maxn][maxn][4],L,R,px[11],py[11],vis[maxn][maxn],Ney[maxn][maxn][4];
char p[maxn][maxn];
bool Vis[maxn][maxn][4],inq[maxn][maxn];
Point Able[maxn*maxn],Now[maxn*maxn];queue <Point> Q1,Q2;void Dfs(int x,int y,int l)
{if (Vis[x][y][l]) {if (!Nex[x][y][l])Nex[x][y][l] = Ney[x][y][l] = -INF;return;}Vis[x][y][l] = cnt;int kl = l;if (p[x][y] == 'A')kl = (kl + 1) % 4;if (p[x][y] == 'C')kl = (kl + 3) % 4;int xx = x + dx[kl];int yy = y + dy[kl];if (xx < 1 || xx > n || yy < 1 || yy > m || p[xx][yy] == 'x') {Nex[x][y][l] = x;Ney[x][y][l] = y;return;}Dfs(xx,yy,kl);Nex[x][y][l] = Nex[xx][yy][kl];Ney[x][y][l] = Ney[xx][yy][kl];
}bool cmp(const Point &A,const Point &B)
{return f[L][R][A.x][A.y] < f[L][R][B.x][B.y];
}void SPFA(int l,int r)
{L = l; R = r;sort(Now + 1,Now + tail + 1,cmp);for (int i = 1; i <= tail; i++)Q1.push(Now[i]);while (!Q1.empty() || !Q2.empty()) {Point k;if (Q1.empty())k = Q2.front(),Q2.pop();else if (Q2.empty())k = Q1.front(),Q1.pop();else {Point k1 = Q1.front();Point k2 = Q2.front();if (f[l][r][k1.x][k1.y] < f[l][r][k2.x][k2.y]) k = k1,Q1.pop();else k = k2,Q2.pop();}vis[k.x][k.y] = 0;for (int Next = 0; Next < 4; Next++) {int xx = Nex[k.x][k.y][Next];int yy = Ney[k.x][k.y][Next];if (xx == -INF) continue;if (f[l][r][xx][yy] > f[l][r][k.x][k.y] + 1) {f[l][r][xx][yy] = f[l][r][k.x][k.y] + 1;if (vis[xx][yy] != cnt) vis[xx][yy] = cnt,Q2.push(Point(xx,yy));if (!inq[xx][yy]) {inq[xx][yy] = 1;Able[++tot] = Point(xx,yy);}}}}
}int main()
{freopen("3205.in","r",stdin);freopen("3205.out","w",stdout);cin >> t >> m >> n;for (int i = 1; i <= n; i++)scanf("%s",p[i] + 1);++cnt;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++) {for (int l = 0; l < 4; l++)if (!Vis[i][j][l])Dfs(i,j,l);if ('1' <= p[i][j] && p[i][j] <= '9') {px[p[i][j] - '0'] = i;py[p[i][j] - '0'] = j;}}for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)for (int l = 1; l <= t; l++)for (int r = l; r <= t; r++)f[l][r][i][j] = INF;for (int i = 1; i <= t; i++) {f[i][i][px[i]][py[i]] = 0;Able[++tot] = Point(px[i],py[i]);inq[px[i]][py[i]] = 1;}for (int k = 0; k < t; k++)for (int l = 1; l <= t; l++) {int r = l + k;if (r > t) break;++cnt; tail = 0;for (int i = 1; i <= tot; i++) {int x = Able[i].x;int y = Able[i].y;for (int K = l; K < r; K++)f[l][r][x][y] = min(f[l][r][x][y],f[l][K][x][y] + f[K+1][r][x][y]);if (f[l][r][x][y] < INF)Now[++tail] = Point(x,y),vis[x][y] = cnt; }SPFA(l,r);}int Ans = INF;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)Ans = min(Ans,f[1][t][i][j]);if (Ans == INF) cout << -1;else cout << Ans;return 0;
}

3205: [Apio2013]机器人相关推荐

  1. [APIO2013]机器人(DP+SPFA最短路)

    [APIO2013]机器人 description solution dpl,r,i,j:dp_{l,r,i,j}:dpl,r,i,j​: 在(i,j)(i,j)(i,j)位置合并编号为[l,r][l ...

  2. bzoj3205: [Apio2013]机器人

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3205 思路:类似斯坦纳树的想法 但是因为这里的合并必须连号 所以子集枚举就变成了区间合并 说 ...

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

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

  4. [APIO2013]机器人(斯坦纳树)

    题目描述 VRI(Voltron 机器人学会)的工程师建造了 n 个机器人.任意两个兼容的机 器人站在同一个格子时可以合并为一个复合机器人. 我们把机器人用 1 至 n 编号(n ≤ 9).如果两个机 ...

  5. 【BZOJ3205_洛谷3638】[APIO2013]机器人(动态规划)

    题目: 洛谷3638 分析: 卡了一天的神题--(OrzJumpmelon) 首先预处理出从点\(p\)向\(d\)方向出发最终能到达的点\(nxt[p][d]\).这个可以直接记忆化搜索解决.如果出 ...

  6. bzoj3205 [Apio2013]机器人

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3205 http://uoj.ac/problem/107 [题解] 我们发现这就是一棵斯坦纳 ...

  7. 【QBXT】学习笔记——Day3/4图论+dp

    继续上传一波笔记吧. Day3 1.16AM 今天讲图论,以习题为主. 开篇水题: 给一幅图,若删去一个点后变成一棵树,则这个点合法.问哪些点合法. 思路根据树的性质:这个点不是割点,m-这个点的度数 ...

  8. [总结]2019年9月 OI学习/刷题记录

    从现在开始记录一下每天的学习情况.主力LOJ? 2019/9/5 LibreOJ #2543. 「JXOI2018」排序问题 答案显然是\(\frac{(n+m)!}{Cnt_1!Cnt_2!\cdo ...

  9. 机器人黑暗面的时代即将到来?

    全文共3205字,预计学习时长6分钟 今年最恐怖的电影不是出自好莱坞之手,而是出自一个致力于将人类从杀人机器中拯救出来智囊团. 电影展示了在不久的将来,在反乌托邦社会中,手掌大小的无人机采用面部识别技 ...

最新文章

  1. 一个n位的数,去掉其中的k位,问怎样去使得留下来的(n-k)位数按原来的前后顺序组成的数最小...
  2. equals属于mysql语句吗_equals和==的区别 (Java基础)
  3. 拒绝不靠谱的需求:怎样确定需求才是正确的?
  4. CSS2-3常见的demo列子总结
  5. mysql树节点路径,关于mysql:从使用物化路径编码树的表中选择,按深度优先排序(无递归/ ltree)...
  6. FileWriter和FileReader解析
  7. 基于光强的角点检测(SUSAN角点检测、FAST角点检测、FAST-ER角点检测)
  8. 华为P30 Pro终极渲染图曝光:后置徕卡四摄颜值出众
  9. Ajax.dll 使用
  10. python和java哪个好-Python和JAVA的就业前景哪个好点?
  11. 怎么让envi中影像背景为0_eCogniton波段权重设置——基于ENVI的波段信息量计算
  12. 【2013高考作文】重庆作文
  13. c语言程序设计答案四,C语言程序设计练习四(参考答案)
  14. Xmind8 绿色版安装教程
  15. 吉林大学计算机学院三等奖学金,吉林大学奖学金评定方案.doc
  16. 北斗导航 | ARAIM算法初探:使用精密单点定位(PPP)技术的ARAIM:解分离
  17. vue2 学习之路 常见的指令!
  18. 《信息物理融合系统(CPS)设计、建模与仿真——基于 Ptolemy II 平台》——2.2 令牌和数据类型...
  19. iMonitor 365 远程监控软件怎样管理员工电脑?
  20. MXC_UART 内核调用过程

热门文章

  1. 最新 抖音 X-Gorgon 0408 和8408 设备注册协议
  2. html里position属性,科技常识:详解html中 position属性用法(四种)
  3. 对魔兽攻击伤害算法及平衡性的研究
  4. base64stego
  5. mysql利用frm和_mysql怎么通过frm和ibd文件还原数据
  6. SuperMap iServer 许可切换
  7. 创建java取消module_在idea 中添加和删除模块Module操作
  8. ubuntu下mosquitto的配置
  9. 锂离子电池储能系统安全标准(1)
  10. 【Firefox】火狐浏览器网页翻译,只需代码加入书签即可