您的位置:首页 > 其它

POJ 3083 Children of the Candy Corn

2012-02-24 10:01 253 查看
这一题是比较麻烦的深搜加广搜的题,考察范围较广,题目大意是从起点出发分别找出左贴墙走、右贴墙与正常走到终点的最短路程。很自然联想到用广搜解决正常走的最短路径,用深搜解决另两种最短路程。难点是如何解决深搜时的方向问题,由于不会用C++提供的STL中德队列类,所以就自己写的,比较麻烦,不过思路应该还算清晰吧。

AC代码如下:

#include <iostream>
#define MAX 100
#define MAXN 10000
using namespace std;
char map[MAX][MAX];
int vis[MAX][MAX];
int dir1[4][2]={{0,-1},{1,0},{0,1},{-1,0}};//左优先,逆时针选择方向
int dir2[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//右优先,顺时针选择方向
int w, h;
int d1, d2;
struct queue{
int x, y, dis;
};
struct queue que[MAXN];
struct queue s_pos;//用于记录S点的坐标

void ini()
{
int i, j;
scanf("%d%d", &w, &h);
for(i = 0; i < h; i++)
for(j = 0; j < w; j++)
{
cin >> map[i][j];
if(map[i][j] == 'S')//记录S的坐标
{
s_pos.x = i;
s_pos.y = j;
}
}
if(s_pos.x == 0)//因为由于S的位置不同第一步的方向也不同,所以要分情况讨论
{    d1 = 1; d2 = 1;}
else if(s_pos.x == h - 1)
{   d1 = 3; d2 = 3;}
else if(s_pos.y == 0)
{   d1 = 2; d2 = 0;}
else if(s_pos.y == w - 1)
{   d1 = 0; d2 = 2;}
}
int bfs(int si, int sj)
{
int di[4] = {1, 0, -1, 0}, dj[4] = {0, 1, 0, -1};
int front = 0, rear = 1, k, ti, tj;
memset(vis, 0, sizeof(vis));
que[0].x = si; que[0].y = sj; que[0].dis = 1;//将S点的坐标放在队列中的第一位
vis[si][sj] = 1;
while(front < rear)
{
if(map[que[front].x][que[front].y] == 'E')
return que[front].dis+=2;//由于S跟E都要算一步,所以+2
for(k = 0; k < 4; k++)//枚举四个方向
{
if(front == 0)//对刚开始时的方向进行讨论
{
if(que[0].x == 0)
{    que[rear].x = si + 1; que[rear].y = sj;}
else if(si == h - 1)
{    que[rear].x  = si - 1; que[rear].y = sj;}
else if(sj == 0)
{    que[rear].y  = sj + 1; que[rear].x = si;}
else if(sj == w - 1)
{    que[rear].y  = sj - 1; que[rear].x = si;}
vis[que[rear].x][que[rear].y] = 1;
rear++;
break;
}
else
{
ti = que[front].x + di[k]; tj = que[front].y + dj[k];//派生出的新坐标
if(!vis[ti][tj] && map[ti][tj] != '#')
{
vis[ti][tj] = 1;
que[rear].x = ti; que[rear].y = tj;//将新坐标放入队尾
que[rear++].dis = que[front].dis + 1;//距离在前一点得基础上+1
}
}
}
front ++;
}
}
int dfs(int x, int y, int d, int dir[][2])
{
int step, tmpx, tmpy, tmp;
if (map[x][y] == 'E')
return 1;
for(int i = 0; i < 4; i++)
{
tmp = (d + i)%4;
tmpx = x + dir[tmp][1];//派生出的新坐标
tmpy = y + dir[tmp][0];
if(tmpx >= 0&&tmpx < h && tmpy >= 0 && tmpy < w && map[tmpx][tmpy]!='#')
break;//找到第一个可走的店
}
step = dfs(tmpx, tmpy, (tmp + 3)%4, dir)+1;//递归找下一个点
return step;
}
int main()
{
int n;
int min_line;
int r_line, l_line;
while(scanf("%d", &n)!= EOF)
{
while(n--)
{
ini();
min_line = bfs(s_pos.x, s_pos.y);
l_line = dfs(s_pos.x, s_pos.y, d1, dir1);
r_line = dfs(s_pos.x, s_pos.y, d2, dir2);
printf("%d %d %d\n", l_line, r_line, min_line);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: