uoj #107. 【APIO2013】ROBOTS

 

#107. 【APIO2013】ROBOTS

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

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

例如,22 号机器人只可以与 11 号或 33 号机器人合并。若 22 号机器人与 33 号机器人合并,可构成编号为 232−3 的复合机器人。如果编号为 232−3 的复合机器人与编号为 464−6 的复合机器人合并,可构成编号为 262−6 的复合机器人。当所有机器人合并以后则构成 1n1−n 复合机器人。

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

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

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

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

输入格式

输入的第 11 行包含 33 个正整数 n,wn,w 和 hh,用空格隔开。

输入文件中接下来的 hh 行描述初始时刻房间内的信息,每行包含 ww 个字符。

这 w×hw×h 个字符中每一个表示房间中的一个格子,意义如下:

  • 1’ 至 ‘9’:表示该方格中有一个机器人,编号为这个数字;
  • x’:表示该方格有障碍物;
  • A’:表示该方格中有一个逆时针转向器;
  • C’:表示该方格中有一个顺时针转向器;
  • .’:表示该方格为空地。

输出格式

你的程序必须输出到标准输出。输出仅一个整数,表示最少需要推动的次数。

若不能使所有机器人全部合并,输出 1−1。

样例一

input

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

output

5

explanation

第一步:向右推动 33 号机器人,当它碰到转向器后会向上继续移动,直至碰到墙壁停止移动。

第二步:向上推动 44 号机器人,当它碰到墙壁后停止移动,与 33 号机器人合并,构成 343−4 号机器人。

第三步:向上推动 22 号机器人,当它碰到转向器后会向左移动,由于左侧为墙壁,故停留在原地。

第四步:向右推动 22 号机器人,由于它在一个转向器上,故它会向上移动,直至碰到墙壁停止移动,与 11 号机器人合并,构成 121−2 号机器人。

第五步:向左推动 343−4 号机器人,当它碰到墙壁后停止移动,与 121−2 号机器人合并,构成 141−4 号机器人。

限制与约定

我们将使用以下 44 类输入测例测试你的程序。

  1. (10 分) 满足 n=2n=2,w10w≤10 且 h10h≤10,没有任何转向器。
  2. (20 分) 满足 n=2n=2,w10w≤10 且 h10h≤10。
  3. (30 分) 满足 n9n≤9,w300w≤300 且 h300h≤300。
  4. (40 分) 满足 n9n≤9,w500w≤500 且 h500h≤500。

时间限制2s2s

空间限制256MB

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 501
using namespace std;
int to[maxn*maxn][4],cnt,n,m,pos1,pos2,dis[maxn*maxn][2];
int e[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
char map[maxn][maxn];
bool vis[maxn*maxn];
int make(int x,int y){return (x-1)*m+y;}
int find(int x,int y,int d){
    int prex=x,prey=y;
    while(1){
        if(x>n||x<1||y>m||y<1||map[x][y]=='x'){return make(prex,prey);}
        prex=x;prey=y;
        if(map[prex][prey]=='A'){
            d--;
            if(d<0)d+=4;
        }
        else if(map[prex][prey]=='C'){
            d++;
            if(d>3)d-=4;
        }
        x=prex+e[d][0];y=prey+e[d][1];
        
    }
}
void bfs(int pos,bool wh){
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(pos);vis[pos]=1;
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=0;i<4;i++){
            int t=to[now][i];
            if(!vis[t]){
                dis[t][wh]=dis[now][wh]+1;
                vis[t]=1;
                q.push(t);
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&cnt,&m,&n);
    for(int i=1;i<=n;i++)
        scanf("%s",map[i]+1);
    memset(to,-1,sizeof(to));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            int now=make(i,j);
            if(map[i][j]=='x')continue;
            for(int k=0;k<4;k++)
                to[now][k]=find(i,j,k);
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(map[i][j]=='1')pos1=make(i,j);
            if(map[i][j]=='2')pos2=make(i,j);
        }
    memset(dis,0x3f,sizeof(dis));
    dis[pos1][0]=0;
    dis[pos2][1]=0;
    bfs(pos1,0);
    bfs(pos2,1);
    int ans=dis[0][0]+dis[0][0];
    for(int i=1;i<=n*m;i++)
        if(dis[i][0]+dis[i][1]<ans)ans=dis[i][0]+dis[i][1];
    if(ans>=dis[0][0])puts("-1");
    else printf("%d",ans);
    return 0;
}
30分 双向搜索 暴力

 

posted @ 2018-04-13 18:02  Echo宝贝儿  阅读(167)  评论(0)    收藏  举报