PKU 2488 深度优先搜索

背景:对于有些问题没有好的算法去求解,只能通过遍历搜索的方式寻找可行解,此时就用到了宽度优先搜索和深度优先搜索。深度优先搜索用栈实现,可以利用系统的栈区递归调用,也可以自己维护好结构。一般来说,自己维护栈对空间的把握更准确一些,而且调试也更方便一些。不过递归调用的方式有时确会写出很漂亮的代码,深度搜索随着问题规模增加时间开销会显著增加,此时必须通过一些剪枝技术来进行优化。宽度优先搜索用队列来实现,随问题规模增加空间开销会显著增加。

 

题意:给出棋盘行列数,求从(1,1)点能否遍历整个棋盘,能顺序打印路径,不能则打印"impossible"

注意:

1、行是数字, 列是字母。输出答案要进行排序,先字母非降序,再数字非降序。这要求方向数组数据有次序,这样遍历结果自然有序。

2、行、列的范围是1到26.

3、每组输出前都有"Scenario #id:",输出结束要有回车。不能打印"impossible",能的话顺序打印路径并且按照先字母再数字的次序。

 

示意图:

PKU 2488 深度优先搜索_第1张图片

 

源代码:

#include <iostream> #include <cstring> #include <stack> using namespace std; struct node{//x、y坐标,d是方向索引 node(int a,int b,int c):x(a),y(b),d(c){} int x, y; int d; }; const int N = 26;//行、列规模 bool isUsed[N][N];//标记数组 int r,c;//全局行、列数 stack<node*> s;//保存路径 inline bool isOK(int x, int y)//此点是否满足要求 { return (x>=0 && x<r && y>=0 && y<c && !isUsed[x][y]); } struct offset{ int x, y;//x is num and y is capital, we should keep y undescendly and x undescendly }off[8]={ {-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2} };//方向索引数组,已经按先字母后数字非降排序 const int off_num = sizeof(off)/sizeof(offset);//方向索引数目 int dfs(int x, int y){ int curX = x, curY = y, d=0, i; s.push(new node(x,y,-1)); memset(isUsed,false,sizeof(isUsed)); isUsed[x][y]=true; while(!s.empty() && s.size()!=r*c){ curX = s.top()->x; curY = s.top()->y; for(i=d;i<off_num;i++){ //找到合适点进行进栈 if(isOK(curX+off[i].x, curY+off[i].y)){ curX += off[i].x; curY += off[i].y; s.push(new node(curX, curY, i)); isUsed[curX][curY]=true; d=0; break; } } if(i==off_num){ //所有方向不符合,弹栈 isUsed[curX][curY]=false; d=s.top()->d+1; s.pop(); } } return s.size()==r*c? 0 : 1; } int main() { int t; cin >> t; for(int i=1;i<=t;i++){ cin >> r >> c; cout << "Scenario #" << i << ":" << endl; if(dfs(0,0) == 0){ stack<node*> tmp; while(!s.empty()){ tmp.push(s.top()); s.pop(); } while(!tmp.empty()){ cout <<(char)(tmp.top()->y+'A')<<(tmp.top()->x+1); tmp.pop(); } cout << endl << endl; }else{ cout << "impossible" << endl << endl; } } return 0; }

你可能感兴趣的:(PKU 2488 深度优先搜索)