赞
踩
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始状态和目标状态,找到一种最少步骤的移动方法,实现从初始状态到目标状态的转变。
例如:
输入棋子在棋盘的初始状态及目标状态,注第一个3×3为初始状态,第二个3×3为目标状态,且数字之间以空格分开,如:
3 1 2
4 0 5
6 7 8
0 1 2
3 4 5
6 7 8
输出棋盘初始状态及每步的移动结果,直到目标状态,如:
initial
3 1 2
4 0 5
6 7 8step 1
3 1 2
0 4 5
6 7 8
step 2
0 1 2
3 4 5
6 7 8
1.盲搜(无向导搜索)
采用广搜的方法,实现无向导搜索。
#include<iostream> #include<map> #include<queue> using namespace std; queue<int>Qtmp; map<int,int>pointex; map<int,int>count; map<int,int>qifazhi; map<int,int>pointdir; int resultsum[100]; int dir[4][2]={-1,0,0,1,1,0,0,-1}; int point[3][3]; int r,c; int qifa(int sum0,int end0){ int result=0; if((sum0/100000000==0)&&(end0/100000000==0)){ result++; } while((sum0%10!=0)&&(end0%10!=0)&&(sum0/10!=0)){ if(sum0%10==end0%10){ result++; } sum0=sum0/10; end0=end0/10; } return result; } int move(int u,int d) { int tmp=0; int nr=r+dir[d][0]; int nc=c+dir[d][1]; point[r][c]=point[nr][nc]; point[nr][nc]=0; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) tmp=tmp*10+point[i][j]; } return tmp; } int formulate(int s,int endsum0) { Qtmp.push(s); pointex[s]=1; count[s]=0; int number=0; while(Qtmp.size()) { int u,v; u=Qtmp.front(); Qtmp.pop(); if(u==endsum0){ return count[u]; } int minqifa=move(u,0); for(int i=0;i<4;i++) { bool fool=true; int uu=u; for(int ii=2;ii>=0;ii--) { for(int jj=2;jj>=0;jj--) { point[ii][jj]=uu%10; uu/=10; if(point[ii][jj]==0) { r=ii; c=jj; } } } if((i==0&&r==0)||(i==1&&c==2)||(i==2&&r==2)||(i==3&&c==0)){ fool=false; } if(fool) { v=move(u,i); if(!pointex[v]) { int qifatmp=qifa(v,endsum0); if(qifatmp<=minqifa){ pointex[v]=1; count[v]=count[u]+1; pointdir[v]=i; Qtmp.push(v); number++; } } } } if(number>100){ return -1; } } return -1; } int main() { int end[3][3]; int endsum=0; int beginsum=0; int result; for(int i=0;i<3;i++){ for(int j=0;j<3;j++) { cin>>point[i][j]; beginsum=beginsum*10+point[i][j]; } } for(int i=0;i<3;i++){ for(int j=0;j<3;j++) { cin>>end[i][j]; endsum=endsum*10+end[i][j]; } } result=formulate(beginsum,endsum); resultsum[result+1]=endsum; int endr0,endc0; int temp=endsum; for(int i=2;i>=0;i--) { for(int j=2;j>=0;j--) { end[i][j]=temp%10; temp/=10; if(end[i][j]==0) { endr0=i; endc0=j; } } } int tmpsum; //cout<<result<<endl; if(result==-1){ cout<<"no answer"<<endl; } if(result!=-1){ for(int i=result;i>0;i--){ if(pointdir[endsum]==0){ end[endr0][endc0]=end[endr0+1][endc0]; end[endr0+1][endc0]=0; tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2]; resultsum[i]=tmpsum; endr0=endr0+1; } if(pointdir[endsum]==1){ end[endr0][endc0]=end[endr0][endc0-1]; end[endr0][endc0-1]=0; tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2]; resultsum[i]=tmpsum; endc0=endc0-1; } if(pointdir[endsum]==2){ end[endr0][endc0]=end[endr0-1][endc0]; end[endr0-1][endc0]=0; tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2]; resultsum[i]=tmpsum; endr0=endr0-1; } if(pointdir[endsum]==3){ end[endr0][endc0]=end[endr0][endc0+1]; end[endr0][endc0+1]=0; tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2]; resultsum[i]=tmpsum; endc0=endc0+1; } endsum=tmpsum; } for(int i=1;i<result+2;i++){ if(i==1){ cout<<"initial"<<endl; } else{ cout<<"step "<<i-1<<endl; } int k=0; for(int j=100000000;j>0;j=j/10){ cout<<resultsum[i]/j<<" "; resultsum[i]=resultsum[i]-resultsum[i]/j*j; k++; if(k%3==0){ cout<<endl; } } cout<<endl; } } system("pause"); return 0; }
2.启发式搜索(有向导搜索)
新增启发函数,实现有向导搜索,大大减少搜索时间。
#include<iostream> #include<map> #include<queue> using namespace std; queue<int>Qtmp; map<int,int>pointex; map<int,int>count; map<int,int>pointdir; int resultsum[100]; int dir[4][2]={-1,0,0,1,1,0,0,-1}; int point[3][3]; int r,c; int qifa(int sum0,int end0){ int result=0; if((sum0/100000000==0)&&(end0/100000000==0)){ result++; } while((sum0%10!=0)&&(end0%10!=0)&&(sum0/10!=0)){ if(sum0%10==end0%10){ result++; } sum0=sum0/10; end0=end0/10; } return result; } int move(int u,int d) { int tmp=0; int nr=r+dir[d][0]; int nc=c+dir[d][1]; point[r][c]=point[nr][nc]; point[nr][nc]=0; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) tmp=tmp*10+point[i][j]; } return tmp; } int formulate(int s,int endsum0) { Qtmp.push(s); pointex[s]=1; count[s]=0; int number=0; while(Qtmp.size()) { int u,v; u=Qtmp.front(); Qtmp.pop(); if(u==endsum0){ return count[u]; } int minqifa=100; for(int i=0;i<4;i++) { bool fool=true; int uu=u; for(int ii=2;ii>=0;ii--) { for(int jj=2;jj>=0;jj--) { point[ii][jj]=uu%10; uu/=10; if(point[ii][jj]==0) { r=ii; c=jj; } } } if((i==0&&r==0)||(i==1&&c==2)||(i==2&&r==2)||(i==3&&c==0)){ fool=false; } if(fool) { v=move(u,i); if(!pointex[v]) { int qifatmp=qifa(v,endsum0); if(qifatmp<=minqifa){ minqifa=qifatmp; pointex[v]=1; count[v]=count[u]+1; pointdir[v]=i; Qtmp.push(v); number++; } } } } if(number>100){ return -1; } } return -1; } int main() { int end[3][3]; int endsum=0; int beginsum=0; int result; for(int i=0;i<3;i++){ for(int j=0;j<3;j++) { cin>>point[i][j]; beginsum=beginsum*10+point[i][j]; } } for(int i=0;i<3;i++){ for(int j=0;j<3;j++) { cin>>end[i][j]; endsum=endsum*10+end[i][j]; } } result=formulate(beginsum,endsum); resultsum[result+1]=endsum; int endr0,endc0; int temp=endsum; for(int i=2;i>=0;i--) { for(int j=2;j>=0;j--) { end[i][j]=temp%10; temp/=10; if(end[i][j]==0) { endr0=i; endc0=j; } } } int tmpsum; //cout<<result<<endl; if(result==-1){ cout<<"no answer"<<endl; } if(result!=-1){ for(int i=result;i>0;i--){ if(pointdir[endsum]==0){ end[endr0][endc0]=end[endr0+1][endc0]; end[endr0+1][endc0]=0; tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2]; resultsum[i]=tmpsum; endr0=endr0+1; } if(pointdir[endsum]==1){ end[endr0][endc0]=end[endr0][endc0-1]; end[endr0][endc0-1]=0; tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2]; resultsum[i]=tmpsum; endc0=endc0-1; } if(pointdir[endsum]==2){ end[endr0][endc0]=end[endr0-1][endc0]; end[endr0-1][endc0]=0; tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2]; resultsum[i]=tmpsum; endr0=endr0-1; } if(pointdir[endsum]==3){ end[endr0][endc0]=end[endr0][endc0+1]; end[endr0][endc0+1]=0; tmpsum=end[0][0]*100000000+end[0][1]*10000000+end[0][2]*1000000+end[1][0]*100000+end[1][1]*10000+end[1][2]*1000+end[2][0]*100+end[2][1]*10+end[2][2]; resultsum[i]=tmpsum; endc0=endc0+1; } endsum=tmpsum; } for(int i=1;i<result+2;i++){ if(i==1){ cout<<"initial"<<endl; } else{ cout<<"step "<<i-1<<endl; } int k=0; for(int j=100000000;j>0;j=j/10){ cout<<resultsum[i]/j<<" "; resultsum[i]=resultsum[i]-resultsum[i]/j*j; k++; if(k%3==0){ cout<<endl; } } cout<<endl; } } system("pause"); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。