题意:
在所给的图中(每个点有8个方向可以走)找出一条路径,并且这条路径最多只有一个90度的角。使得这条路径的长度最长。
思路:
*当时看到这题好开心,之前在刘汝佳那本书上做过类似的,WA了三次到最后都没调出来哪里错了= =。进爷看我如此乏力,遂上去直接搞了一发,直接A了。Orz
进爷做法是每次都枚举一个点的八个方向,直走一段距离,然后转一个弯,看看所能获得的最大距离,两个距离加起来即可。
bfs:
dis[x][y][d],表示走到(x,y)点朝向为d的最远距离;
cot[x][y][d],表示走到(x,y)点朝向为d时是否有转过弯;(0:无;1:有)
AC代码:
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 105;
const int INF = 0x3f3f3f3f;
int dir[8][2] = {{0,1}, {-1,1}, {-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
int dis[MAXN][MAXN][10];
int cot[MAXN][MAXN][10];
char ch[MAXN][MAXN];
int n;
struct pp
{
int x, y, z;
};
void bfs(int h1, int h2, int h3)
{
dis[h1][h2][h3] = 1;
queue <pp> q;
q.push((pp){h1, h2, h3});
while(!q.empty())
{
pp e = q.front();
q.pop();
int x, y, z;
for(int i = 0;i < 8; i++)
{
x = e.x+dir[i][0], y = e.y+dir[i][1], z = i;
int tmp =( e.z+6 )% 8, tmp2 = (e.z+2)%8;
if(i != tmp2 && i != tmp && i != e.z) continue; //fangxiangbudui
if(e.z != z && cot[e.x][e.y][e.z] == 1) continue; //ever turn;
if(x >= 0 && y >= 0 && x < n && y < n && (dis[e.x][e.y][e.z] + 1 > dis[x][y][z]||(dis[e.x][e.y][e.z]+1 == dis[x][y][z] && cot[e.x][e.y][e.z] == 0)) && ch[x][y] != '#')// ||后面的那个条件调死我了!!后来才醒悟,如果距离相等,肯定要没转过弯的。
{
dis[x][y][z] = dis[e.x][e.y][e.z]+1;
cot[x][y][z] = cot[e.x][e.y][e.z];
if(e.z != z) cot[x][y][z] = 1;
q.push((pp){x, y, z});
}
}
}
}
int main()
{
while(scanf("%d", &n), n)
{
memset(dis, 0, sizeof(dis));
memset(cot, 0, sizeof(cot));
getchar();
for(int i = 0;i < n; i++)
scanf("%s", ch[i]);
//
for(int i = 0;i < n; i++)
{
for(int j = 0;j < n; j++)
{
if(ch[i][j] == '#') continue;
for(int z = 0;z < 8; z++)
{
if(dis[i][j][z] != 0) continue;
bfs(i, j, z);
}
}
}
//
int res = 2;
for(int i = 0;i < n; i++)
{
for(int j = 0;j < n; j++)
{
if(ch[i][j] == '#') continue;
for(int z = 0;z < 8; z++)
res = max(res, dis[i][j][z]);
}
}
printf("%d\n", res);
}
return 0;
}