zoj3865
解題思路:
首先這道題求的是起點到終點之間的最短到達時間。我們可以維護一個三維的狀態(x,y,direct),其中direct是光標指向的方向,可以理解爲機器人robot是有方向的。光標所在的方向即爲當前位置robot所面對的方向。如此一來,每一秒鐘對於robot可以有四種操作:
- 朝着當前面對的方向前進一格,對應於題中按下一個按鈕,機器人向對應方向移動
- 轉變一次面朝的方向。對應於題中光標左移一格或者光標右移一格。
原地不動。
需要值得注意的是,每過p秒所有按鈕會向右移動一格,也就是說若當前節點的時間模p爲0,則應該(direct+3)%4,(direct = 0,1,2,3分別對應於左,右,上,下)。而此操作必須在此節點入隊前處理,否則vis數組含義錯誤。
由於寬搜的性質,若取出隊頭節點爲終點節點,即可保證其時間花費是最少。也正好說明了vis數組的必要性。
另外,對於第三種操作,即原地不動,如果原地不動後,沒有發生因時間模p爲0而導致的按鈕右移而使狀態發生改變,那麼就不應該入隊此新節點。此處要注意邏輯關係。
下面帖代碼:
#include <cstdio>
#include <cstring>
#include <queue>
#define maxsize 12
using namespace std;
int ns, m, p;
char afx[maxsize][maxsize];
bool vis[maxsize][maxsize][4];
int sx, sy, ex, ey;
const int xx[] = {0, 0, -1, 1};
const int yy[] = { -1, 1, 0, 0};
struct node
{
int x;
int y;
int ti;
int direc;
node()
{}
node(int a, int b, int c, int d)
{
x = a;
y = b;
ti = c;
direc = d;
}
};
int bfs()
{
std::queue <node> q;
vis[sx][sy][0] = true;
node start = node(sx, sy, 0, 0);
q.push(start);
while(!q.empty())
{
node n = q.front();
q.pop();
if(n.x == ex && n.y == ey)
return n.ti;
int nx = n.x + xx[n.direc];
int ny = n.y + yy[n.direc];
node next = node(nx, ny, n.ti + 1, n.direc);
if(next.ti % p == 0)
next.direc = (next.direc + 3) % 4;
if(nx < ns && nx >= 0 && ny < m && ny >= 0 && afx[nx][ny] != '*' && !vis[nx][ny][next.direc])
{
q.push(next);
vis[nx][ny][next.direc] = true;
}
node next4 = node(n.x, n.y, n.ti + 1, (n.direc + 3) % 4);
if(next4.ti % p == 0)
next4.direc = (next4.direc + 3) % 4;
if(!vis[next4.x][next4.y][next4.direc])
{
q.push(next4);
vis[next4.x][next4.y][next4.direc] = true;
}
node next2 = node(n.x, n.y, n.ti + 1, (n.direc + 1) % 4);
if(next2.ti % p == 0)
next2.direc = (next2.direc + 3) % 4;
if(!vis[next2.x][next2.y][next2.direc])
{
q.push(next2);
vis[next2.x][next2.y][next2.direc] = true;
}
node next3 = node(n.x, n.y, n.ti + 1, n.direc);
if(next3.ti % p == 0)
{
next3.direc = (next3.direc + 3) % 4;
}
if(!vis[next3.x][next3.y][next3.direc])
{
q.push(next3);
vis[next3.x][next3.y][next3.direc] = true;
}
}
return -1;
}
void initial()
{
for(int i = 0; i < ns; i++)
for(int j = 0; j < m; j++)
{
if(afx[i][j] == '@')
{
sx = i;
sy = j;
}
else if(afx[i][j] == '$')
{
ex = i;
ey = j;
}
}
memset(vis, false, sizeof(vis));
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d%d", &ns, &m, &p);
for(int i = 0; i < ns; i++)
scanf("%s", afx[i]);
initial();
int ans = bfs();
if(ans != -1)
printf("%d\n", ans);
else
printf("YouBadbad\n");
}
return 0;
}