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;}}
- HDOJ 1043 Eight
- poj1077 /hdoj 1043 Eight
- HDOJ-1043-Eight
- HDOJ 题目1043 Eight(单向BFS,康拓展开,打表)
- hdoj 2514 Another Eight Puzzle(DFS)
- (全排列)Another Eight Puzzle--HDOJ
- poj 1077-Eight;hdu 1043-Eight
- hdu 1043 Eight
- HDU 1043 Eight
- 周赛 HDU 1043 Eight
- Hdu 1043 Eight
- HDU 1043 Eight
- HDU 1043 Eight
- HDU 1043 Eight
- HDU 1043 Eight
- hdu 1043 Eight
- hud 1043 Eight
- HDU 1043 Eight
- Java,从控制台中输入数据的方法——Scanner
- 查看pfring(pf_ring)的配置
- Linux命令--gzip,bzip2,tar,zip命令使用方法详解
- android手机短信拦截的实现
- ListControl的使用步骤
- HDOJ 1043 Eight
- Java for循环遍历数组
- 使用eclipse制作jar文件详细步骤
- 怎样不用中间变量temp 实现两个数交换
- 基于feng streaming server 搭建Android直播测试平台
- Java UDP协议传对象
- android make相关
- 在Winform中点击按钮时不显示边框
- PMIC设置亮度的寄存器