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