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