ccf—I'm stuck!

问题描述
  给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思:
  '#': 任何时候玩家都不能移动到此方格;
  '+': 当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
  '-': 当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非'#'方格移动一格;
  '|': 当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非'#'方格移动一格;
  '.': 当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为'#',则玩家不能再移动;
  'S': 玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
  'T': 玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格。
  此外,玩家不能移动出地图。
  请找出满足下面两个性质的方格个数:
  1. 玩家可以从初始位置移动到此方格;
  2. 玩家不可以从此方格移动到目标位置。
输入格式
  输入的第一行包括两个整数R 和C,分别表示地图的行和列数。(1 ≤ R, C ≤ 50)。
  接下来的R行每行都包含C个字符。它们表示地图的格子。地图上恰好有一个'S'和一个'T'。
输出格式
  如果玩家在初始位置就已经不能到达终点了,就输出“I'm stuck!”(不含双引号)。否则的话,输出满足性质的方格的个数。
样例输入
5 5
--+-+
..|#.
..|##
S-+-T
####.
样例输出
2
样例说明
  如果把满足性质的方格在地图上用'X'标记出来的话,地图如下所示:
  --+-+
  ..|#X
  ..|##
  S-+-T

  ####X



这道题思路是,先从起点出发,用dfs遍历一次(走过的点不重复),先看起点能否走到终点,如果走不到,则返回0,输出I'm stuck,程序结束;

否则:

遍历时记下路过的每个结点的后面遍历中是否能走到结点;

 但后续遍历没走到终点不代表这个结点走不到终点,记下这些点,放到一个队列中;同时,对后续已经能到终点的点做标记,后面有用;

再对队列里的点 ,用dfs遍历,若能走到已经做标记的点(就是后续能走到终点的点) 那么直接确认能走到终点,若走不到,则count++;


#include<iostream>
#include<cstring>
#include<queue>
#include<utility>
using namespace std;



//m2记录本次有没有访问过,m3记录这个点后续能不能走到终点
int r,c,**m2,**m3,count=0,t1,t2;
char**map;
queue <pair<int,int> > q;



//从起点遍历用的dfs函数
int fun(int x,int y){
if(x<0||x>=r||y<0||y>=c)return 0;
if(map[x][y]=='#') return 0;
if(m3[x][y]) return 1;
if(map[x][y]=='T')m3[x][y]=1;
if(m2[x][y]) return 0;
char t=map[x][y];
//cout<<x<<" "<<y<<endl; 
m2[x][y]=1;
switch(t){
case '+':{
if(fun(x+1,y)) m3[x][y]=1;
if(fun(x-1,y)) m3[x][y]=1;
if(fun(x,y+1)) m3[x][y]=1;
if(fun(x,y-1)) m3[x][y]=1;
break;
}
case 'S':{
if(fun(x+1,y)) m3[x][y]=1;
if(fun(x-1,y)) m3[x][y]=1;
if(fun(x,y+1)) m3[x][y]=1;
if(fun(x,y-1)) m3[x][y]=1;
break;
}
case 'T':{
if(fun(x+1,y)) m3[x][y]=1;
if(fun(x-1,y)) m3[x][y]=1;
if(fun(x,y+1)) m3[x][y]=1;
if(fun(x,y-1)) m3[x][y]=1;
break;
}
case '|':{
if(fun(x+1,y)) m3[x][y]=1;
if(fun(x-1,y)) m3[x][y]=1;
break;
}
case '-':{
if(fun(x,y+1)) m3[x][y]=1;
if(fun(x,y-1)) m3[x][y]=1;
break;
}
case'.':{
if(fun(x+1,y)) m3[x][y]=1;
break;
}


}
if(!m3[x][y]) { q.push(make_pair(x,y));return 0;}
else return 1;
}


//从队列里点出发用的dfs函数(区别是 这个不用记录入队列)
int fun2(int x,int y){
if(x<0||x>=r||y<0||y>=c)return 0;
if(map[x][y]=='#') return 0;
if(m3[x][y]) return 1;
if(map[x][y]=='T')m3[x][y]=1,cout<<"t";
if(m2[x][y]) return 0;
char t=map[x][y];
m2[x][y]=1;
switch(t){
case '+':{
if(fun2(x+1,y)) m3[x][y]=1;
if(fun2(x-1,y)) m3[x][y]=1;
if(fun2(x,y+1)) m3[x][y]=1;
if(fun2(x,y-1)) m3[x][y]=1;
break;
}
case 'S':{
if(fun2(x+1,y)) m3[x][y]=1;
if(fun2(x-1,y)) m3[x][y]=1;
if(fun2(x,y+1)) m3[x][y]=1;
if(fun2(x,y-1)) m3[x][y]=1;
break;
}
case 'T':{
if(fun2(x+1,y)) m3[x][y]=1;
if(fun2(x-1,y)) m3[x][y]=1;
if(fun2(x,y+1)) m3[x][y]=1;
if(fun2(x,y-1)) m3[x][y]=1;
break;
}
case '|':{
if(fun2(x+1,y)) m3[x][y]=1;
if(fun2(x-1,y)) m3[x][y]=1;
break;
}
case '-':{
if(fun2(x,y+1)) m3[x][y]=1;
if(fun2(x,y-1)) m3[x][y]=1;
break;
}
case'.':{
if(fun2(x+1,y)) m3[x][y]=1;
break;
}


}
if(!m3[x][y]) { return 0;}
else return 1;
}


int main(){
//freopen ("F:\\1.txt", "r", stdin);
cin>>r>>c;
int x,y;
map=new char*[r];
m2=new int*[r];
m3=new int*[r];
for(int i=0;i<r;i++)
{
map[i]=new char[c];
m2[i]=new int[c];
m3[i]=new int[c];
for(int j=0;j<c;j++)
{
cin>>map[i][j],m2[i][j]=0,m3[i][j]=0;
if(map[i][j]=='S') x=i,y=j;}
}
if(!fun(x,y)) {
cout<<"I'm stuck!";
return 0;}




while(!q.empty()){
//memset(m2,0,sizeof(m2));


for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
{
m2[i][j]=0;}}

pair<int,int> p;
p=q.front();
if(!fun2(p.first,p.second) )count++;
q.pop();
//cout<<"gg"<<endl;
}
cout<<count;
//fclose(stdin);
return 0;
}


猜你喜欢

转载自blog.csdn.net/var1994/article/details/51100561