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