1379 八数码难题
作者:互联网
1379 八数码难题
这道题我本来想使用HASH+MAP来练练手,结果发现用A*+ID更简单
也就是说,这道题使用的是A算法+迭代加深算法进行一个估价函数和固定层数再加上优化的时间,来AC这一道题
首先,我们输入的这个起始状态用数组存储,不过记住目标状态的数组要多加一圈零,否则会导致移位时的越界现象,这样更加方便
然后进行一个特殊判断check也就是如果当前的起始状态和目标状态已经相等,就不必要进行下面的操作了
然后循环枚举搜索的深度,也就是迭代加深,接下来A算法进行搜索
A*算法的搜索是一个关键,在这里我们设置的估计函数其实就是方位数组,每次都得也即是从上下左右的进行一个估价,如果当前状态加上估价值如果不越界,那么就将这两个位置换一下,进行递归,记得要回溯优化怎么办?
那么如何进行一个剪枝优化呢?只需要哦每次再搜索的时候,用一个flag标记,如果到头了就不用接下来算法,其实就是判断两个限制:一个是迭代的搜索层数,一个是搜索的九宫格只有行列为3,如果当前状态超出就没必要进行接下来的搜索了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
char ss[15];
int ans[4][4]=
{//目标状态
{0,0,0,0},
{0,1,2,3},
{0,8,0,4},
{0,7,6,5}
};
int a[5][5];//初始状态
int k,flag;//k为深度 flag为标记
int dx[]={0,1,-1,0};
int dy[]={1,0,0,-1};//方位数组,也是估价函数
bool check()
{//特判函数
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
{
if(ans[i][j]!=a[i][j]) return 0;
}
return 1;
}
bool test(int step)
{//判断是否达到目标
int sum=0;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(ans[i][j]!=a[i][j]&&++sum+step>k)
{
return 0;
}
}
}
return 1;
}
void A_star(int step,int x,int y,int p)
{
if(step==k)//搜索到头了
{
if(check()) flag=1;
return;
}
if(flag) return; //剪枝
for(int i=0;i<4;i++)
{
int vx,vy;
vx=x+dx[i],vy=y+dy[i];//估价步数
if(vx<1||vx>3||vy<1||vy>3||p+i==3) continue;//越界,不符合答案
swap(a[x][y],a[vx][vy]);//交换
if(test(step)&&flag==0) A_star(step+1,vx,vy,i);
swap(a[x][y],a[vx][vy]);//回溯
}
}
int main()
{
int x,y;//存储0的位置
cin>>ss;
for(int i=0;i<9;i++)
{
a[i/3+1][i%3+1]=ss[i]-'0';//存储
if(ss[i]-'0'==0) x=i/3+1,y=i%3+1;
}
if(check())
{
cout<<0<<endl;
return 0;
}
while(++k)//扩大深度
{
A_star(0,x,y,-1);//限制层数
if(flag)
{
cout<<k<<endl;
break;
}
}
return 0;
}
标签:难题,return,int,step,flag,数码,1379,vy,include 来源: https://blog.csdn.net/CCCCDEV_CCCC/article/details/116836354