#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;}