题目大意:给出一个迷宫,要求从一点到另一点过程中转弯必须是90度或者不转,次数不能超过一次的最远距离长度。
解题思路:还是补一下广州赛区的题解吧,虽然这个赛区是我们做的最不好的。不过可喜可贺的是西安赛区因为我们第一个题开始交的时候系统出问题一直没返回结果,最后重判我们那道题ac了,因此顺利晋级了,虽然还在等结果,不过已经胸有成竹了,算是给我们努力这么久一份回报吧!回到这个题来,比赛的时候纠结惨了,没有告诉起点,我们想遍历每一个可以作为起点的点,有怕数据卡时间,会T。结果一次WA了之后,改成这样的结果A了,时间还是比较乐观的。这个题直接根据题意用DFS进行模拟即可,code给出了详细的注释,详见code。
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=5024
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100+10;
int n,ans;
char map[MAXN][MAXN];
int vis[MAXN][MAXN];
int dir[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
struct node{
int x,y,cnt,tmp,count;
}s,t;
void dfs(node st){
for(int i=0;i<8;++i){ //八个方向的遍历
t.x=st.x+dir[i][0];
t.y=st.y+dir[i][1];
if(t.x>=0 && t.x<n && t.y>=0 && t.y<n && map[t.x][t.y]=='.' && !vis[t.x][t.y]){ //边界以及条件判断
t.cnt=st.cnt+1; //步长加1
t.tmp=i; //方向置为i,表示从哪个方向过来的
t.count=st.count; //同步转弯次数
vis[t.x][t.y]=1; //访问标记
if(st.tmp==-1) dfs(t); //如果是第一次进来,则下次可以任意方向访问
else if(st.tmp==0 || st.tmp==4){ //如果是0,4方向,则下次只能继续或访问垂直的2,6方向且转弯次数不能超过1,下同
if(i==2 || i==6){if(++t.count<=1) dfs(t);}
else if(i==0 || i==4) dfs(t);
}
else if(st.tmp==1 || st.tmp==5){
if(i==3 || i==7){if(++t.count<=1) dfs(t);}
else if(i==1 || i==5) dfs(t);
}
else if(st.tmp==2 || st.tmp==6){
if(i==0 || i==4){if(++t.count<=1) dfs(t);}
else if(i==2 || i==6) dfs(t);
}
else if(st.tmp==3 || st.tmp==7){
if(i==1 || i==5){if(++t.count<=1) dfs(t);}
else if(i==3 || i==7) dfs(t);
}
}
}
ans=max(ans,st.cnt); //每次更新最大值
}
int main(){
//freopen("input.txt","r",stdin);
while(~scanf("%d",&n) && n){
getchar();
for(int i=0;i<n;++i) //接收图
scanf("%s",&map[i]);
ans=0;
for(int i=0;i<n;++i) //起点和终点未知,因此遍历整个点,取最大的值作为结果
for(int j=0;j<n;++j){
memset(vis,0,sizeof(vis)); //每次初始化访问数组
if(map[i][j]=='.'){
s.x=i;s.y=j;
s.cnt=1;s.tmp=-1; //步长初始化为1,方向初始化为-1
s.count=0; //转弯次数初始化为0
vis[s.x][s.y]=1; //访问标记
dfs(s);
}
}
printf("%d\n",ans);
}
return 0;
}