题意:
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
解法:
A*
#include<iostream>
#include<queue>
#include<map>
#define END 123804765
using namespace std;
struct node
{
int now,step,g;
bool operator < (const node &x)const
{
return x.g<g;
}
};
int end[9]={1,2,3,8,0,4,7,6,5};
int a[9];
priority_queue<node> q;
node tmp;
map<int,int> m;
inline int fnd(int x);
inline int abs(int x);
void in();
void move(int i,int t);
void out(int x);
int g(int now,int step);
int main()
{
int s;
cin>>s;
tmp.now=s; tmp.step=0; tmp.g=0;
q.push(tmp);
while(1)
{
int x;
tmp=q.top(); q.pop();
if(m.count(tmp.now))
continue;
m[tmp.now]=1;
if(tmp.now==END)
{
cout<<tmp.step;
return 0;
}
out(tmp.now);
for(int i=0;i<9;i++)
if(!a[i])
{
x=i;
break;
}
if((x+1)%3) //right
move(x,1);
if(x%3) //left
move(x,-1);
if(x>=0&&x<=5) //up
move(x,3);
if(x>=3&&x<=8) //down
move(x,-3);
}
return 0;
}
int g(int x,int step)
{
int ans=step*2;
for(int i=0;i<9;i++)
ans+=abs(fnd(a[i])-i);
return ans;
}
void out(int x)
{
for(int i=8;i>=0;i--)
{
a[i]=x%10;
x/=10;
}
}
void move(int i,int t)
{
if(i+t<=8&&i+t>=0)
{
swap(a[i],a[i+t]);
in();
swap(a[i],a[i+t]);
}
}
void in()
{
int ans=0;
for(int i=0;i<9;i++)
ans=ans*10+a[i];
node z;
z.step=tmp.step+1; z.now=ans;
z.g=g(ans,z.step);
//m[ans]=1;
q.push(z);
}
inline int abs(int x)
{
return x>0?x:-1;
}
inline int fnd(int x)
{
switch(x)
{
case 1 : return 0;
case 2 : return 1;
case 3 : return 2;
case 4 : return 5;
case 5 : return 8;
case 6 : return 7;
case 7 : return 6;
case 8 : return 3;
case 0 : return 4;
}
}
原文地址:https://www.cnblogs.com/nenT/p/11761319.html
时间: 2024-11-07 21:44:06