这篇文章分享八数码难题的几种解法
暴力广搜
#include<bits/stdc++.h>
#define int long long
using namespace std;
string start;
string ed="123804765";
queue<string> q;
map<string,int> dis;
int bx[5]={0,0,1,-1};
int by[5]={1,-1,0,0};
void dfs(){
q.push(start);
while(!q.empty()){
string t=q.front();
int dist=dis[t];
q.pop();
if(t==ed){
cout<<dis[t];
return;
}
int k=t.find('0');
int x=k/3,y=k%3;
for(int i=0;i<4;i++){
int xx=x+bx[i];
int yy=y+by[i];
if(xx<3&&xx>=0&&yy<3&&yy>=0){
swap(t[k],t[xx*3+yy]);
if(dis[t]==0){
dis[t]=dist+1;
q.push(t);
}
swap(t[k],t[xx*3+yy]);
}
}
}
}
signed main(){
cin>>start;
dfs();
}
双向搜索
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int g=123804765;
map<int,int>ans;
map<int,int>v;
queue<int>q;
int a[4][4];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void sorce(){
if(n==g){
printf("0");
return;
}
q.push(n);
q.push(g);
ans[n]=0;
ans[g]=1;
v[g]=2;
v[n]=1;
while(!q.empty()){
int now,cur=q.front();
q.pop();
now=cur;
int fx,fy;
for(int i=3;i>=1;i--)
for(int j=3;j>=1;j--){
a[i][j]=now%10;
now/=10;
if(a[i][j]==0)fx=i,fy=j;
}
for(int i=0;i<4;i++){
int nx=fx+dx[i];
int ny=fy+dy[i];
if(nx<1||nx>3||ny<1||ny>3)continue;
swap(a[nx][ny],a[fx][fy]);
now=0;
for(int p=1;p<=3;p++)
for(int j=1;j<=3;j++)
now=now*10+a[p][j];
if(v[now]==v[cur]){
swap(a[nx][ny],a[fx][fy]);
continue;
}
if(v[now]+v[cur]==3){
printf("%lld",ans[now]+ans[cur]);
return;
}
ans[now]=ans[cur]+1;
v[now]=v[cur];
q.push(now);
swap(a[nx][ny],a[fx][fy]);
}
}
}
signed main(){
scanf("%lld",&n);
sorce();
}
A* (启发式搜索)
#include<bits/stdc++.h>
#define int long long
using namespace std;
string endd="123804765";
struct node{
int f,step;
string now;
bool operator <(const node &x)const{
return f>x.f;
}
};
int h(string cur){
int cnt=0;
for(int i=0;i<9;i++){
if(endd[i]!=cur[i]&&cur[i]!=0)cnt++;
}
return cnt;
}
string start;
map<string,int>mp;
map<string,int>dis;
priority_queue<node>q;
int dx[5]={0,0,1,-1};
int dy[5]={1,-1,0,0};
void astar(){
q.push(node{h(start),0,start});
mp[start]=1;
dis[start]=0;
while(q.size()){
node t=q.top();
q.pop();
string cur=t.now;
if(cur==endd){
cout<<t.step;
exit(0);
}
int x,y;
for(int i=0;i<9;i++){
if(cur[i]=='0')x=i/3,y=i%3;
}
int k1=x*3+y;
for(int i=0;i<4;i++){
int xx=x+dx[i];
int yy=y+dy[i];
if(xx<0||xx>2||yy<0||yy>2)continue;
int k2=xx*3+yy;
swap(cur[k1],cur[k2]);
if(mp[cur]==0||(mp[cur]==1&&(t.step+1)<dis[cur])){
dis[cur]=t.step+1;
q.push(node{h(cur)+dis[cur],dis[cur],cur});
mp[cur]=1;
}
swap(cur[k1],cur[k2]);
}
}
}
signed main(){
cin>>start;
if(h(start)==0){
printf("0");
return 0;
}
astar();
}
IDA*(迭代加深)
#include<bits/stdc++.h>
using namespace std;
int dep;
string start;
string endd="123804765";
int h(string s){
int cnt=0;
for(int i=0;i<9;i++)if(s[i]!=endd[i]&&s[i]!='0')cnt++;
return cnt;
}
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
bool dfs(int now,int pre){//U422821
if(start==endd)return true;
if(now>=dep)return false;
int x,y,k1;
for(int i=0;i<9;i++){
if(start[i]=='0'){
x=i/3;
y=i%3;
k1=i;
}
}
for(int i=0;i<4;i++){
int xx=x+dx[i];
int yy=y+dy[i];
int k2=xx*3+yy;
if(xx<0||yy<0||xx>2||yy>2||k2==pre)continue;
swap(start[k1],start[k2]);
if(dfs(now+1,k1))return true;
swap(start[k1],start[k2]);
}
return false;
}
signed main(){
cin>>start;
dep=h(start);
while(!dfs(0,-1))dep++;
printf("%d",dep);
}
11

被折叠的 条评论
为什么被折叠?



