1. 程式人生 > >BFS:中國象棋中的跳馬問題

BFS:中國象棋中的跳馬問題

問題描述是這樣的:

有一張p*q的棋盤,並且棋盤中有障礙物(用來限制馬的行動,即中國象棋中的蹩馬腿)。有一個棋子馬(走“日”字形路線),要從起始點走到終點。

輸入部分:

第一行輸入一個整數n,表示有n組測試例項,每組測試資料第一行輸入兩個整數p和q,表示棋盤的大小(1<=p,q<=100),每組測試資料第二行輸入4個整數x1,y1,x2,y2,表示馬的起點和終點的座標。第三行輸入一個整數m,表示圖中有多少障礙物,接著m行每行一個座標,分別表示m個障礙物的位置座標。

輸出部分:

輸出馬從起始位置走到終點所需的最小步數。若馬不能走到終點,輸出“ can not reach!”

樣例輸入:

2
9 10
1 1 2 3
0
9 10
1 1 2 3
8
1 2
2 2
3 3
3 4
1 4
3 2
2 4
1 3

樣例輸出

1

can not reach!

分析:對於此題,考慮到要求最小步數,我們選擇廣搜。先把馬的起始點入隊,然後用廣搜的思想把此點能到達的其他點加入佇列,這裡需要一個數組s來記錄每一點是否已經入隊,我們只把那些沒有被標記過的點入隊,直到佇列中的元素為空,或者搜到了終點,搜尋結束,然後輸出即可。

其實我感覺本題比較有特色的地方就是馬的“日”字形走法了,雖然用一個2維陣列就能簡化,但還要注意和移動方向陣列之間的一一對應關係。比如,馬開始在(0,0)點,如果(0,1)處有障礙物,那麼馬就不能走到(-1,2)和(1,2)這兩點了,此時方向陣列和馬的走法陣列之間就有(0,-1)和(1,-2)(-1,-2)之間的對應。

實現程式碼如下:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef struct node
{
    int x,y,step;
}queue;
queue que[11000];
int q,p,sx,sy,ex,ey;
int map[105][105];
bool s[105][105];
int hdir[8][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};//注意這裡要和上面的馬的路徑相對應
void bfs()
{
    int a=1,b=1;
    int x,y,hx,hy;
    que[a].x=sx;
    que[a].y=sy;
    que[a].step=0;
    s[sx][sy]=true;
    while(a<=b&&!s[ex][ey])
    {
        x=que[a].x;
        y=que[a].y;
        for(int i=0;i<8;i++)
          if(!map[x+dir[i/2][0]][y+dir[i/2][1]])
          {
              hx=x+hdir[i][0];
              hy=y+hdir[i][1];
              if(hx>0&&hx<=q&&hy>0&&hy<=p&&!s[hx][hy]&&!map[hx][hy])
              {
                  b++;
                  que[b].x=hx;
                  que[b].y=hy;
                  que[b].step=que[a].step+1;
                  s[hx][hy]=true;
              }
          }
        a++;
    }
    if(a>b) puts("can not reach!");
    else printf("%d\n",que[b].step);
}
int main()
{
    int m,n,a,b;
    cin>>n;
    while(n--)
    {
        memset(map,0,sizeof(map));
        memset(s,false,sizeof(s));
        scanf("%d%d",&p,&q);
        scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&a,&b);
            map[a][b]=1;
        }
        bfs();
    }
    return 0;
}