HDOJ 1043 Eight

来源:互联网 发布:苹果电脑桌面软件设置 编辑:程序博客网 时间:2024/06/05 11:06

                用了五天左右做了一下八数码的问题,所谓的八重境界也就是实现了四种而已,但是心里已经感觉实在坐不下去了,就这样总结一下吧。八数码问题使用了两点辅助工具。第一是曼哈顿距离,用来作为A*的h函数以及IDA*的剪枝。第二是康拓展开,用来标识已经遍历过的状态。第三是逆序数,作为问题的剪枝。参考代码中的运行时间和内存大小仅供参考吧,毕竟使用了STL的栈,速度方面会有影响。毕竟每次末尾还要做清理工作。其实用数组代替效率会更高些,但是内存也会消耗更厉害些。

方法一:预处理+反向宽度优先搜索       Exe.Time    562MS    Exe.Memory    19592K

//#include<fstream>#include <iostream>#include<string>#include<queue>using namespace std;#define N 9#define NMAX 362885struct Point{char eightMap[N];int position;string path;};const int fac[]={1,1,2,6,24,120,720,5040,40320};//康托序列const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};const char option[4]={'u','l','d','r'};bool visited[NMAX];string inversionPath[NMAX];inline int cantor(Point p){int ans=0;for(int i=0;i<N;i++){int cnt=0;for(int k=i+1;k<N;k++){if(p.eightMap[k]<p.eightMap[i])cnt++;}ans+=fac[8-i]*cnt;}return ans;}bool bfs(){int row,col,cantorValue;memset(visited,false,sizeof(visited));Point startPoint;for (int i=1;i<N;i++)startPoint.eightMap[i-1]=i+'0';startPoint.eightMap[N-1]='x';startPoint.position=N-1;startPoint.path="";visited[0]=true;queue<Point> que;que.push(startPoint);while(!que.empty()){Point p=que.front();que.pop();for(int i=0;i<4;i++){row=p.position/3+dir[i][0];col=p.position%3+dir[i][1];if(row<0||col<0||row>=3||col>=3) continue;Point newPoint(p);newPoint.eightMap[newPoint.position]=newPoint.eightMap[col+row*3];newPoint.position=col+row*3;newPoint.eightMap[newPoint.position]='x';cantorValue=cantor(newPoint);if(visited[cantorValue]) continue;visited[cantorValue]=true;newPoint.path+=option[i];inversionPath[cantorValue]=newPoint.path;que.push(newPoint);}}return false;}int main(){//fstream cin("Eight.txt");Point startPoint;int startCantor;bfs();while(cin>>startPoint.eightMap[0]){if(startPoint.eightMap[0]=='x')startPoint.position=0;for(int i=1;i<9;i++)  {cin>>startPoint.eightMap[i];if(startPoint.eightMap[i]=='x')startPoint.position=i;}startCantor=cantor(startPoint);if(visited[startCantor]){for (int i=inversionPath[startCantor].size()-1;i>=0;i--)cout<<inversionPath[startCantor][i];cout<<endl;}else{cout<<"unsolvable"<<endl;}}return 0;}

方法二:双向宽度优先搜索       Exe.Time 1046MS         Exe.Memory   10784K

//#include<fstream>#include <iostream>#include<string>#include<queue>#include <algorithm>using namespace std;#define N 9#define NMAX 362885struct Point{char eightMap[N];int position;string path;};Point startPoint;queue<Point> que,inversionQue;const int fac[]={1,1,2,6,24,120,720,5040,40320};//康托序列const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};const char option[4]={'d','r','u','l'};const char inversionOption[4]={'u','l','d','r'};char visited[NMAX];string path[NMAX];string result;bool flag;inline int cantor(Point p){int ans=0;for(int i=0;i<N;i++){int cnt=0;for(int k=i+1;k<N;k++){if(p.eightMap[k]<p.eightMap[i])cnt++;}ans+=fac[8-i]*cnt;}return ans;}inline bool inversionNumberCheck(){int cnt=0;for(int i=0;i<N;i++){if(startPoint.eightMap[i]=='x') continue;for(int k=i-1;k>=0;k--){if(startPoint.eightMap[k]=='x') continue;if(startPoint.eightMap[k]>startPoint.eightMap[i]) cnt++;}}return cnt&1;}void bfs(){int row,col,cantorValue;Point p=que.front();que.pop();for(int i=0;i<4;i++){row=p.position/3+dir[i][0];col=p.position%3+dir[i][1];if(row<0||col<0||row>=3||col>=3) continue;Point newPoint(p);newPoint.eightMap[newPoint.position]=newPoint.eightMap[col+row*3];newPoint.position=col+row*3;newPoint.eightMap[newPoint.position]='x';cantorValue=cantor(newPoint);if(visited[cantorValue]==1) continue;newPoint.path+=option[i];if(visited[cantorValue]==2){flag=false;reverse(path[cantorValue].begin(),path[cantorValue].end());result=newPoint.path+path[cantorValue];return ;}path[cantorValue]=newPoint.path;visited[cantorValue]=1;que.push(newPoint);}}void inversionBfs(){int row,col,cantorValue;Point p=inversionQue.front();inversionQue.pop();for(int i=0;i<4;i++){row=p.position/3+dir[i][0];col=p.position%3+dir[i][1];if(row<0||col<0||row>=3||col>=3) continue;Point newPoint(p);newPoint.eightMap[newPoint.position]=newPoint.eightMap[col+row*3];newPoint.position=col+row*3;newPoint.eightMap[newPoint.position]='x';cantorValue=cantor(newPoint);if(visited[cantorValue]==2) continue;newPoint.path+=inversionOption[i];if(visited[cantorValue]==1){flag=false;reverse(newPoint.path.begin(),newPoint.path.end());result=path[cantorValue]+newPoint.path;return ;}path[cantorValue]=newPoint.path;visited[cantorValue]=2;inversionQue.push(newPoint);}}int main(){//fstream cin("Eight.txt");Point endPoint;int cnt;for (int i=1;i<N;i++)endPoint.eightMap[i-1]=i+'0';endPoint.eightMap[N-1]='x';endPoint.position=N-1;endPoint.path="";while(cin>>startPoint.eightMap[0]){if(startPoint.eightMap[0]=='x')startPoint.position=0;for(int i=1;i<9;i++)  {cin>>startPoint.eightMap[i];if(startPoint.eightMap[i]=='x')startPoint.position=i;}if(inversionNumberCheck()){cout<<"unsolvable"<<endl;continue;}int startCantor=cantor(startPoint);if(startCantor==0){cout<<endl;continue;}memset(visited,false,sizeof(visited));while(!inversionQue.empty())inversionQue.pop();while(!que.empty())que.pop();flag=true;inversionQue.push(endPoint);visited[0]=2;que.push(startPoint);visited[startCantor]=1;while(flag){cnt=inversionQue.size();while(cnt--&&flag)inversionBfs();cnt=que.size();while(cnt--&&flag)bfs();}cout<<result<<endl;}return 0;}

方法三:A-Star算法           Exe.Time  1078MS          Exe.Memory   2636K

//#include<fstream>#include <iostream>#include<string>#include<queue>#include <stack>using namespace std;#define N 9struct Point{char eightMap[N];int position;int g,f;friend bool operator< (const Point& a,const Point& b){return a.f>b.f;}}startPoint;const int fac[]={1,1,2,6,24,120,720,5040,40320};//康托序列const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};const char option[4]={'d','r','u','l'};bool visited[363000];int pre[363000]; char op[363000];stack<char> stk;inline int cantor(Point p){int ans=0;for(int i=0;i<N;i++){int cnt=0;for(int k=i+1;k<N;k++){if(p.eightMap[k]<p.eightMap[i])cnt++;}ans+=fac[8-i]*cnt;}return ans;}inline int ABS(int x){return x<0?-x:x;}inline int h(Point p){int val=0;for(int i=0;i<N;i++){if(p.eightMap[i]=='x') continue;int c=p.eightMap[i]-'1';val+=ABS(c/3-i/3)+ABS(c%3-i%3);}return val;}bool bfs(){int row,col,cantorValue;memset(visited,false,sizeof(visited));priority_queue<Point> que;que.push(startPoint);while(!que.empty()){Point p=que.top();que.pop();for(int i=0;i<4;i++){row=p.position/3+dir[i][0];col=p.position%3+dir[i][1];if(row<0||col<0||row>=3||col>=3) continue;Point newPoint(p);newPoint.eightMap[newPoint.position]=newPoint.eightMap[col+row*3];newPoint.position=col+row*3;newPoint.eightMap[newPoint.position]='x';cantorValue=cantor(newPoint);if(visited[cantorValue]) continue;visited[cantorValue]=true;newPoint.g++;newPoint.f=newPoint.g+h(newPoint);pre[cantorValue]=cantor(p);op[cantorValue]=option[i];if(cantorValue==0) return true;que.push(newPoint);}}return false;}inline bool inversionNumberCheck(){int cnt=0;for(int i=0;i<N;i++){if(startPoint.eightMap[i]=='x') continue;for(int k=i-1;k>=0;k--){if(startPoint.eightMap[k]=='x') continue;if(startPoint.eightMap[k]>startPoint.eightMap[i]) cnt++;}}return cnt&1;}int main(){//fstream cin("Eight.txt");while(cin>>startPoint.eightMap[0]){if(startPoint.eightMap[0]=='x')startPoint.position=0;for(int i=1;i<9;i++)  {cin>>startPoint.eightMap[i];if(startPoint.eightMap[i]=='x')startPoint.position=i;}if(inversionNumberCheck()){cout<<"unsolvable"<<endl;continue;}startPoint.g=0;startPoint.f=h(startPoint);int startCantor=cantor(startPoint);bfs();int index=0;while(index!=startCantor){stk.push(op[index]);index=pre[index];}while(!stk.empty()){cout<<stk.top();stk.pop();}cout<<endl;}}

方法四:IDA*算法              Exe.Time    2609MS              Exe.Memory   952K

//#include<fstream>#include <iostream>using namespace std;#define N 9struct Point{char eightMap[N];int position;}startPoint;const int fac[]={1,1,2,6,24,120,720,5040,40320};//康托序列const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};const char option[4]={'d','r','u','l'};bool visited[362885];char op[362885];int deep;bool flag;inline int cantor(Point p){int ans=0;for(int i=0;i<N;i++){int cnt=0;for(int k=i+1;k<N;k++){if(p.eightMap[k]<p.eightMap[i])cnt++;}ans+=fac[8-i]*cnt;}return ans;}inline int ABS(int x){return x<0?-x:x;}inline int h(Point p){int val=0;for(int i=0;i<N;i++){if(p.eightMap[i]=='x') continue;int c=p.eightMap[i]-'1';val+=ABS(c/3-i/3)+ABS(c%3-i%3);}return val;}void dfs(int d){int check=h(startPoint);if(check==0){flag=false;return ;}if(check+d>deep) return ;int row,col,cantorValue;for(int i=0;i<4;i++){row=startPoint.position/3+dir[i][0];col=startPoint.position%3+dir[i][1];if(row<0||col<0||row>=3||col>=3) continue;Point p(startPoint),assistPoint(startPoint);p.eightMap[p.position]=p.eightMap[col+row*3];p.position=col+row*3;p.eightMap[p.position]='x';cantorValue=cantor(p);if(visited[cantorValue]) continue;visited[cantorValue]=true;op[d]=option[i];startPoint=p;dfs(d+1);if(!flag) return ;startPoint=assistPoint;visited[cantorValue]=false;}return ;}inline bool inversionNumberCheck(){int cnt=0;for(int i=0;i<N;i++){if(startPoint.eightMap[i]=='x') continue;for(int k=i-1;k>=0;k--){if(startPoint.eightMap[k]=='x') continue;if(startPoint.eightMap[k]>startPoint.eightMap[i]) cnt++;}}return cnt&1;}int main(){//fstream cin("Eight.txt");while(cin>>startPoint.eightMap[0]){if(startPoint.eightMap[0]=='x')startPoint.position=0;for(int i=1;i<9;i++)  {cin>>startPoint.eightMap[i];if(startPoint.eightMap[i]=='x')startPoint.position=i;}if(inversionNumberCheck()){cout<<"unsolvable"<<endl;continue;}deep=h(startPoint);memset(visited,false,sizeof(visited));memset(op,false,sizeof(op));flag=true;while(flag){deep++;dfs(0);}for (int i=0;op[i]!=NULL;i++)//不能以deep作为终点否则,如果op清空,则会产生空格;如果op为清空,则输出错误的字符cout<<op[i];cout<<endl;}}
原创粉丝点击