随机传送迷宫“盛大游戏杯”第15届上海大学程序设计联赛夏季赛

随机传送迷宫

发布时间: 2017年7月9日 20:20   最后更新: 2017年7月10日 21:13   时间限制: 1000ms   内存限制: 128M

小Y做了一个随机迷宫生成器,生成的迷宫可以用 nm 的矩阵来表示,人物可以从迷宫的起点开始,每个单位时间选择往上下左右走一步,但不能走到不能通行的格子或者走出矩阵外。在迷宫中会有不定数量的传送门,其中传送门入口与传送门出口一一对应,如果人物处在传送门入口处,可以用一个单位的时间使用这个传送门入口到达一个传送门出口处,但是在尝试之前你并不知道哪一个传送门入口对应哪一个出口,因此小Y想知道用什么样的策略走才能在最坏情况下花费最少时间到达迷宫的出口。传送门只能单向通行,但是可以重复使用,由于传送门入口出口一一对应,因此重复使用传送门会到达同一个传送门出口。

第一行有一个整数 T 表示数据组数。( T<=50
接着有 T 组数据,每组数据第一行有两个整数 n m 。( 2<=n , m<=100
接着有 n 行, m 列的迷宫矩阵。
其中字符'S','T'分别表示唯一的迷宫起点和终点,
字符'#'表示无法通行的障碍,
字符'.'表示空地,
字符'i','o'分别表示传送门入口和出口。(传送门入口与出口数量相同,并且数量都不超过5)

对于每组数据输出一行,表示花费的最少单位时间,如果不存在一定能走到出口的方案,则输出-1。

  复制
3
4 4
Siii
..oo
####
T..o
4 4
S..i
i###
#.#o
T.o#
5 4
o.Si
###i
.oo#
i###
i#oT
9
-1
16
想法:
搜索
代码:
#include<iostream>  
#include<algorithm>  
#include<stdio.h>  
#include<string.h>  
#include<queue>  
#define inf 0x3f3f3f3f  
using namespace std;  
typedef long long ll;  
const int mx = 1e2+10,co[4][2]={1,0,0,1,-1,0,0,-1};  
int n,m,cnt1,ans;  
char map[mx][mx];  
struct node{  
    int x,y,k;  
    node(){}  
    node(int xx,int yy,int kk){ x = xx, y = yy, k = kk; }  
}a[5],b[5];  
bool vis2[5];  
int bfs(int beg,int eng){  
    queue<node> skt;  
    bool vis[mx][mx],flag = 0;  
    int sum = inf;  
    memset(vis,0,sizeof(vis));  
    skt.push(node(beg,eng,0));  
    vis[beg][eng]=1;  
    while(!skt.empty()){  
        node no = skt.front();  
        skt.pop();  
        for(int i=0;i<4;i++){  
            node po = node(no.x+co[i][0],no.y+co[i][1],no.k+1);  
            if(po.x<0||po.y<0||po.x>=n||po.y>=m) continue;   
            if(vis[po.x][po.y]||map[po.x][po.y]=='#') continue;  
            vis[po.x][po.y] = 1;  
            if(map[po.x][po.y]=='T') return min(sum,po.k);  
            if(!flag&&map[po.x][po.y]=='i'){  
                map[po.x][po.y] = '.';  
                for(int j=0;j<cnt1;j++){  
                    if(vis2[j]) continue;  
                    vis2[j] = 1;  
                    if(sum==inf)  sum = bfs(b[j].x,b[j].y)+po.k+1;  
                    else sum = max(sum,bfs(b[j].x,b[j].y)+po.k+1);  
                    vis2[j] = 0;  
                }  
                map[po.x][po.y] = 'i';  
                flag = 1;  
            }  
            skt.push(po);  
        }  
    }  
    return sum;  
}  
int main(){  
    int t,beg,eng;  
    scanf("%d",&t);  
    while(t--){  
        ans = 0, cnt1 = 0;  
        scanf("%d%d",&n,&m);  
        for(int i=0;i<n;i++){  
            scanf("%s",map[i]);  
            for(int j=0;j<m;j++){  
                if(map[i][j]=='S') beg = i, eng = j;  
                else if(map[i][j]=='o') b[cnt1++]=node(i,j,0);  
            }  
        }  
        ans = bfs(beg,eng);   
        printf("%d\n",ans>=inf? -1:ans);  
    }  
    return 0;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值