【POJ2488】 A knight's Journey 解題報告 測試數據+代碼+思路

 
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <iostream>
//#define INPUT
//#define DBG
/**
    Problem:POJ2488
    Begin Time:8th/Mar/2012 1:30 p.m.
    End Time:2012-03-08 21:08:53
    Test Data:見下方另一份代碼,數據生成器
    Standard output:以本程序對拼即可。
    知識點:深度優先搜索+回溯,在搜索方向選擇上還考了一個小小的貪心法
    思路:
        Recursive BFS即可。
        以一個數組track記錄當前的路徑。
        indtrack記錄當前track數組中有多少個元素
        當indtrack = p*q的時候退出
        搜索的時候記得向量要按照字母序,也就是說,以-2最爲優先,然後是-1
        然後是1,然後是2
        本解題報告中,x爲字母(A..Z),y爲數字(1...26)
    教訓:
    1.BFS不保證遍歷全圖,所以記得回溯,因爲這個WA了8個小時(在這個條件是的,如果是上下左右4方向或

者8方向的那種,則應該可以不回溯)
    2.BFS在要用回溯的時候,不熟練的時候千萬別用stack,最好還是老老實實遞歸
    3.記錄track的時候不可以用STL裏面的queue,因爲queue.pop始終是pop最頂層元素
    在某一層遞歸回溯的時候,pop的可能是其他遞歸放進去的元素,導致不出最優解。
    4.WA的時候,按照自己的思路走一遍代碼,確認沒問題的時候再看細節
    5.寫搜索的時候要仔細,第一次把搜索向量的 < 8寫成了 < 7,導致WA
    6.千萬別手懶,其實最好按照自己的思路寫幾個測試數據試一試再寫代碼。
    7.遞歸出結果的時候,尤其是這種要記錄路徑的,不要直接在遞歸函數裏寫,要設置一個
    全局布爾變量,然後根據其取值寫,這樣做得好處是
    (1)避免了重複輸出,因爲trackind == p * q的時候可能有一些遞歸還沒有return,會導致重複輸出
    (2)便於輸出和判斷是否impossible
    (3)在isPossible = true的時候所有遞歸return,節省了時間。
    c0de4fun,A AC a day keeps WA away.
*/
using namespace std;
const int c0de4fun = 30;
int movex[8] = {-2,-2,-1,-1,1,1,2,2};
int movey[8] = {-1,1,-2,2,-2,2,-1,1};
int maze[c0de4fun][c0de4fun];
int cntvisited = 0;
bool isPossible = false;
struct node
{
    int x;
    int y;
};
//queue<node> track;
int track[100][3];
int trackind = 0;
void DFS(int X,int Y,int nowx,int nowy)
{
    node tmp;
    node tmp1;
    int tracknow;
    tmp.x = nowx;
    tmp.y = nowy;
    cntvisited++;
    maze[tmp.x][tmp.y] = 1;
    tracknow = trackind;
    if(!isPossible)
    {
    track[tracknow][1] = tmp.x;
    track[tracknow][2] = tmp.y;
    trackind++;
    }
    else
    {
        return;
    }

#ifdef DBG
    printf("Now visit the %c%d \n",tmp.x - 1 + 'A',tmp.y);
#endif
    if( cntvisited == X*Y )
    {
        isPossible = true;
       /* for(int i = 0 ; i < trackind ; i++)
        {
            printf("%c%d",track[i][1] - 1 + 'A',track[i][2]);
        }
        printf("\n");
        return; */
    }
    for(int i = 0 ; i < 8 ; i++)
    {
        tmp1.x = tmp.x + movex[i];
        tmp1.y = tmp.y + movey[i];
        if( tmp1.x > X || tmp1.y > Y
           || tmp1.x < 1 || tmp1.y < 1
           || maze[tmp1.x][tmp1.y] == 1)
           continue;
        DFS(X,Y,tmp1.x,tmp1.y);
    }
    cntvisited--;maze[tmp.x][tmp.y] = 0;
    if(!isPossible)
    {
    track[tracknow][1] = 0 ;
    track[tracknow][2] = 0;
    trackind--;
    }

    return;
}
int main()
{
#ifdef INPUT
    freopen("b:\\acm\\poj2488\\input.txt","r",stdin);
    freopen("b:\\acm\\poj2488\\output_me.txt","w",stdout);
#endif
    int T,P,Q;
    scanf("%d",&T);
    for(int t = 0 ; t < T; t++)
    {
        printf("Scenario #%d:\n",t+1);
        cntvisited = 0;
        trackind = 0;
        isPossible = false;
        memset(track,0,sizeof(int)*200);
        memset(maze,0,sizeof(int)*c0de4fun*c0de4fun);
        scanf("%d%d",&P,&Q);
        DFS(Q,P,1,1);
        if(!isPossible)
        {
            printf("impossible\n");
        }
        else
        {
            for(int i = 0 ; i < trackind; i ++)
            {
                printf("%c%d",track[i][1] - 1 + 'A',track[i][2]);
            }
            printf("\n");
        }
        if ( t != T-1)
            printf("\n");
    }
#ifdef INPUT
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}

測試數據生成代碼:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <time.h>
using namespace std;
const int cases = 5000;
int main()
{
    freopen("b:\\acm\\poj2488\\input.txt","w",stdout);
    int a = 0;
    srand(time(NULL));
    printf("%d\n",cases);
    for(int i = 0 ; i < cases; i++)
    {
        a = rand()%26 + 1;
        printf("%d %d\n",a,26/a);
    }
    fclose(stdout);
 //   cout << "Hello world!" << endl;
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章