马踏棋盘+贪心启发搜索;第一次接触这么高级的搜索-,-;下一步准备学习双向广搜了;

#include <iostream> #include <stack> #include <vector> #include <algorithm> using namespace std; typedef struct { int x; int y; }Direc;//横向x,纵向y,右正,下正 Direc direc[8]={{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1}}; //贪心选择数组元素类 class Greed_Select { friend class Stack_Node; friend class Horse; public: bool operator < (Greed_Select &p) { return way_out<p.way_out; } private: int to_x,to_y; int way_out;//如果此跳点没有出路 }; class Stack_Node//栈结点类 { friend class Horse; public: Stack_Node(int x,int y):_x(x),_y(y),_cnt(0) { } private: int _x,_y; vector<Greed_Select> _to_go;//数组中元素为上边的那个类 int _cnt;//记录该走第几条贪心选择 }; class Horse { public: Horse() { for(int i=0;i<=8;++i) for(int j=0;j<=8;++j) flag[i][j]=0; } void begin() { Stack_Node *start=new Stack_Node(1,1);//从左上角开始跳 _stack.push(start); flag[1][1]=1; _get_greed_select(start); while(!_stack.empty())//用栈深搜+贪心策略 { if(_stack.size()==64)//栈中有64个点,说明整个棋盘都跳过了,找到一种路径,打印,退出. { cout<<"找到一种路径"<<endl; return; } Stack_Node *p=_stack.top(); if(p->_cnt==8||p->_to_go[p->_cnt].way_out==999)//所有邻接跳点都遍历过,退栈.(包括8方向全部遍历过以及从当前点无法到达剩余方向的情况) { flag[p->_x][p->_y]=0; _stack.pop(); delete p; } else//按贪心策略访问还没访问过的邻接跳点 { int tx=p->_to_go[p->_cnt].to_x; int ty=p->_to_go[p->_cnt].to_y; ++p->_cnt; Stack_Node *q=new Stack_Node(tx,ty); flag[tx][ty]=1; cout<<"跳跃到"<<tx<<","<<ty<<endl; _get_greed_select(q); _stack.push(q); } } if(_stack.empty()) { cout<<"没有路径"<<endl; } } void _get_greed_select(Stack_Node *p) { int tx,ty,count; for(int i=0;i<=7;++i) { tx=p->_x+direc[i].x; ty=p->_y+direc[i].y; if(test_bound(tx,ty)&&flag[tx][ty]==0)//能跳过去的邻接跳点,计算出口数量 { count=0; for(int j=0;j<=7;++j) { if(test_bound(tx+direc[j].x,ty+direc[j].y)&&flag[tx+direc[j].x][ty+direc[j].y]==0) { ++count; } } Greed_Select *temp=new Greed_Select; temp->to_x=tx; temp->to_y=ty; temp->way_out=count; p->_to_go.push_back(*temp); } else//跳不过去的邻接跳点 { Greed_Select *temp=new Greed_Select; temp->to_x=-1; temp->to_y=-1; temp->way_out=999; p->_to_go.push_back(*temp); } } sort(p->_to_go.begin(),p->_to_go.end()); } bool test_bound(int x,int y) { return (x>0)&(x<9)&(y>0)&(y<9); } private: stack<Stack_Node*> _stack; unsigned char flag[9][9]; }; int main() { Horse test; test.begin(); }

 

 

问题描述就不写了.

 

算法思想:

基本思想:利用栈实现深搜,每次入栈一个跳点,走到终点或者没有可跳点则退栈一个,继续深搜.

聪明的改进:给这个过程加入一个贪心策略,每次选择周边跳点时, 贪心优先选择一个出口最少的跳点.

这里说的出口是指能够跳到的邻接跳点的数量,当前位于(1,1)的话,可以用好几个跳点,从这些跳点中选出一个这些跳点可选择周边跳点最少的跳点.   贪心的原因据说是因为: 优先选择出口少的点,就可以先把一些遗漏的格子补满, 使得最后剩下的没跳过的点比较多而且密集,这样能最终全跳满的概率就非常大,甚至整个算法只需要入栈64次0回溯直接找到一个路径.

 

每个栈结点保存了当前点坐标,贪心选择跳点的数组,记录已走过的跳点的计数量,当所有邻接跳点都走过,则出栈,否则继续取没走过的邻接跳点深搜.

 

代码写的还稍微有点庞杂,不知道对你有没有帮助.

 

 

你可能感兴趣的:(马踏棋盘+贪心启发搜索;第一次接触这么高级的搜索-,-;下一步准备学习双向广搜了;)