关于有传送门的BFS

关于有传送门的BFS
上次中南中期比赛的题目有个有传送门的BFS题目,这题目之前出现过一次,不过没中南的这个难,题意是在一个矩阵中从S到E,之间1的地方不能走,0的地方能走一步,消耗时间为1,2-9的地方除了能像0一样走,还能传送到相同数字的位置。之前做的那个是p能传送,这题只是传送门种类多了一些,但是解题方法是一样的。
题目链接 http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1259
跳跳 Time Limit: 1 Sec   Memory Limit: 128 MB
SUBMIT: 238   Solved: 62
[SUBMIT] [STATUS]

Description

 一个每块地板标记着0~9某个数字的迷宫,其中标记1的地板不可以走,标记2~9的地板可以不花时间地跳到任意相同数字的位置,也可以和标记0的地板一样向前后左右任意方向花1个单位时间移动1的距离。给出起点和终点,求起点到终点的最短时间。

Input

 每组数据第一行一个n,表示尺寸,2 <= n <= 100。

接下来n行每行n个0~9的字符,或S表示起点,E表示终点,S和E的运动规则与0相同。整个地图只有一个S和一个E。

Output

 每组数据输出一个数,占一行,表示起点到终点可以花费的最短时间。

如果无法到达重点,输出"Oh No!"

Sample Input

5
0S100
00131
00300
00000
003E0
3
S12
010
10E

Sample Output

4
Oh No!

 
 
先把2-9相同点的数字的坐标保存起来,然后就是BFS




#include<cstdio>   
#include<cstring>   
#include<queue>   
using namespace std;  
int n,ex,ey,num[10],sx,sy;  
int dx[]={0,0,1,-1};  
int dy[]={1,-1,0,0};  
char a[105][105];  
bool vis[105][105],flag[10];  
int nd1[10][10000][2];  
struct nd 
{  
 int x;  
 int y;  
 int st;  
};  
int bfs()  
{  
 queue<nd> que;  
 int k,h;  
 struct nd temp,tmp;  
 temp.x=sx;  
 temp.y=sy;  
 temp.st=0;  
 que.push(temp);  
 vis[sx][sy]=true;  
 while(!que.empty())  
 {  
  temp=que.front();  
  que.pop();  
  if(temp.x==ex && temp.y==ey)  
  return temp.st;  
  for(k=0;k<4;k++)  
  {  
   int ii=temp.x+dx[k];  
   int jj=temp.y+dy[k];  
   if(ii>=0&&ii<n&&jj>=0&&jj<n&&!vis[ii][jj]&&a[ii][jj]!='1')  
   {  
    tmp.st=temp.st+1;  
    if(a[ii][jj]>='2' && a[ii][jj]<='9') //当遇到2-9中任意的一个数字的时候就把所有相同坐标的点入队,这样就相当于从所有   
    { //相同点开始一起搜   
     if(flag[a[ii][jj]-'0']==false)  
     {  
      for(h=0;h<num[a[ii][jj]-'0'];h++)  
      {  
       tmp.x=nd1[a[ii][jj]-'0'][h][0];  
       tmp.y=nd1[a[ii][jj]-'0'][h][1];  
       que.push(tmp);  
       vis[tmp.x][tmp.y]=true;  
      }  
      flag[a[ii][jj]-'0']=true;  
     }  
    }  
    else //当遇到 0 时直接入队   
    {  
     tmp.x=ii;  
     tmp.y=jj;  
     que.push(tmp);  
     vis[ii][jj]=true;  
    }  
   }  
  }  
 }  
 return -1;  
}  
int main()  
{  
 int i,j,min;  
 while(scanf("%d",&n)!=EOF)  
 {  
  memset(num,0,sizeof(num));  
  for(i=0;i<n;i++)  
  scanf("%s",a[i]);  
  for(i=0;i<n;i++)  
  for(j=0;j<n;j++)  
  {  
   if(a[i][j]>='2'&&a[i][j]<='9') //用nd1 数组来保存所有相同的点    
   {  
    nd1[a[i][j]-'0'][num[a[i][j]-'0']][0]=i;  
    nd1[a[i][j]-'0'][num[a[i][j]-'0']][1]=j;  
    num[a[i][j]-'0']++;  
   }  
   else if(a[i][j]=='S')  
   {  
    sx=i;  
    sy=j;  
   }  
   else if(a[i][j]=='E')  
   {  
    ex=i;  
    ey=j;  
   }  
  }  
  min=100000000;  
  memset(vis,false,sizeof(vis));  
  memset(flag,false,sizeof(flag));  
  min=bfs();  
  if(min>0)  
   printf("%d\n",min);  
  else  
   printf("Oh No!\n");  
 }  
 return 0;  
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值