题意是:不能回头,但是必须转弯;
难点就在如何表示方向还有如何处理转弯;
要把方向看成图的一个属性,并不一定要按照模拟过程走一遍。
开始突发奇想从终点开始搜,结果把自己搞晕了,还是贴从起点(’@’)开始搜的代码吧。
/**
* hdu2364
* 三维记忆bfs
* 题目要求不能回头,但是可能转多个弯之后又回到走过的点,但还是有可能过去的,因为可能是从不同方向移动到这个点,
* 所以,所以用一个三维的数组记录每一个点的状态,每个点有4种状态,即四个方向
* 要把方向看成图的属性
* ac
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
char map[85][85];
bool visit[85][85][5];
int h, w;
int startx,starty;
struct node
{
node(int _x = 0, int _y = 0, int _d = 0, int _cnt = 0):x(_x),y(_y),d(_d),cnt(_cnt){}
int x;
int y;
int d;
int cnt;//步数
};
node first;
int bfs()
{
queue<node> Q;
Q.push(first);
int next[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
while(!Q.empty())
{
node temp = Q.front();
Q.pop();
if(temp.x == 1 || temp.x == h || temp.y == 1 || temp.y == w)
{
return temp.cnt;
}
for(int k = 0; k < 4; k++)
{
int nowx = temp.x + next[k][0];
int nowy = temp.y + next[k][1];
if(map[nowx][nowy] == '#' || visit[nowx][nowy][k])
{
continue;
}
if(nowx == startx && nowy == starty)
{
continue;
}
if(temp.d%2 == k%2)//k%2 == 0时上下,== 1时左右
{
//如果反向,啥也不做,相当于continue
if(temp.d == k)
{
if(k%2==0 && map[temp.x][temp.y+1] == '#' && map[temp.x][temp.y-1] == '#')
{
visit[nowx][nowy][k] = 1;
Q.push(node(nowx, nowy, k, temp.cnt+1));
}
if(k%2==1 && map[temp.x+1][temp.y] == '#' && map[temp.x-1][temp.y] == '#')
{
visit[nowx][nowy][k] = 1;
Q.push(node(nowx, nowy, k, temp.cnt+1));
}
}
}
else
{
visit[nowx][nowy][k] = 1;
Q.push(node(nowx, nowy, k, temp.cnt+1));
}
}
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(visit, 0, sizeof(visit));
memset(map, 0, sizeof(map));
scanf("%d%d", &h, &w);
for (int i = 1; i <= h; i++)
{
getchar();
for (int j = 1; j <= w; j++)
{
scanf("%c", &map[i][j]);
if (map[i][j] == '@')
{
startx = i;
starty = j;
}
}
}
first.x = startx; first.y = starty; first.d = -1; first.cnt = 0;
int result = bfs();
printf("%d\n", result);
}
return 0;
}
还有优先队列版本:
/**
* hdu2364
* 三维记忆bfs
* 要把方向看成图的属性
* ac
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
char map[85][85];
bool visit[85][85][5];
int h, w;
int startx,starty;
struct node
{
node(int _x = 0, int _y = 0, int _d = 0, int _cnt = 0):x(_x),y(_y),d(_d),cnt(_cnt){}
int x;
int y;
int d;
int cnt;
friend bool operator < (const node &a,const node &b)
{
return a.cnt>b.cnt;
}
};
node first;
int bfs()
{
priority_queue<node> Q;
Q.push(first);
int next[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
while(!Q.empty())
{
node temp = Q.top();
Q.pop();
if(temp.x == 1 || temp.x == h || temp.y == 1 || temp.y == w)
{
return temp.cnt;
}
for(int k = 0; k < 4; k++)
{
int nowx = temp.x + next[k][0];
int nowy = temp.y + next[k][1];
if(map[nowx][nowy] == '#' || visit[nowx][nowy][k])
{
continue;
}
if(nowx == startx && nowy == starty)
{
continue;
}
if(temp.d%2 == k%2)//k%2 == 0时上下,== 1时左右
{
//如果反向,啥也不做,相当于continue
if(temp.d == k)
{
if(k%2==0 && map[temp.x][temp.y+1] == '#' && map[temp.x][temp.y-1] == '#')
{
visit[nowx][nowy][k] = 1;
Q.push(node(nowx, nowy, k, temp.cnt+1));
}
if(k%2==1 && map[temp.x+1][temp.y] == '#' && map[temp.x-1][temp.y] == '#')
{
visit[nowx][nowy][k] = 1;
Q.push(node(nowx, nowy, k, temp.cnt+1));
}
}
}
else
{
visit[nowx][nowy][k] = 1;
Q.push(node(nowx, nowy, k, temp.cnt+1));
}
}
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(visit, 0, sizeof(visit));
memset(map, 0, sizeof(map));
scanf("%d%d", &h, &w);
for (int i = 1; i <= h; i++)
{
getchar();
for (int j = 1; j <= w; j++)
{
scanf("%c", &map[i][j]);
if (map[i][j] == '@')
{
startx = i;
starty = j;
}
}
}
first.x = startx; first.y = starty; first.d = -1; first.cnt = 0;
int result = bfs();
printf("%d\n", result);
}
return 0;
}