其他分享
首页 > 其他分享> > 1379 八数码难题

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