题目大意:在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
思路:使用IDA*算法。估价函数为现在棋盘与目标棋盘的对应元素不同的个数。剪枝:若当前深度加上估价函数值大于限定的深度则剪枝。搜索时,每次拿出估价函数最小的节点进行扩展,这一操作利用优先队列支持。整体上属于广搜。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int tar[5][5]={
{0,0,0,0,0},
{0,1,2,3,0},
{0,8,0,4,0},
{0,7,6,5,0},
{0,0,0,0,0}
};
const int dx[5]={0,-1,1,0,0};
const int dy[5]={0,0,0,1,-1};
const int mod=100007;
struct node
{
int x,y,eva,id,map[5][5];
bool operator <(const node &a) const
{
return eva>a.eva;
}
};
int map[5][5],ans=10000,maxdep,x,y;
bool flag=0;
void init()
{
char ch[10];
scanf("%s",ch);
int i,k=0,j=1;
for (i=0;i<=8;++i) /*先转化为矩阵形式*/
{
k++;
if (k>3)
{
k%=3;
j++;
}
map[j][k]=ch[i]-‘0‘;
if (ch[i]==‘0‘)
{
x=j;
y=k;
}
}
}
node addnode(int x,int y,int eva,int id,int map[5][5])
{
node tmp;
tmp.x=x;
tmp.y=y;
tmp.eva=eva;
tmp.id=id;
memcpy(tmp.map,map,sizeof(tmp.map));
return tmp;
}
int evaluate(int map[5][5])
{
int res=0;
for (int i=1;i<=3;++i)
for (int j=1;j<=3;++j)
if (map[i][j]!=tar[i][j])
res++;
return res;
}
priority_queue<node> q;
void idastar()
{
int i,j,k,tmp=evaluate(map);
while (!q.empty())
q.pop();
q.push(addnode(x,y,tmp,0,map));
while (!q.empty())
{
node best=q.top();
q.pop();
if (best.eva==0)
{
flag=1;
break;
}
int x=best.x,y=best.y;
int nowmap[5][5];
memcpy(nowmap,best.map,sizeof(nowmap));
for (i=1;i<=4;++i)
{
int xx=x+dx[i];
int yy=y+dy[i];
if (xx<1 || xx>3 || yy<1 || yy>3)
continue;
swap(nowmap[x][y],nowmap[xx][yy]);
int noweva=evaluate(nowmap);
if (noweva+best.id<ans && noweva+best.id<=maxdep)
{
q.push(addnode(xx,yy,noweva,best.id+1,nowmap));
}
swap(nowmap[x][y],nowmap[xx][yy]);
}
}
}
int main()
{
init();
for (maxdep=0;maxdep<=100;++maxdep) /*限定深度*/
{
idastar();
if (flag)
{
printf("%d",maxdep);
break;
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/little_flower_0/article/details/47810811