luogu#P1379 八数码难题

题意:

在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;
	}
}

posted @ 2019-10-29 20:24  nenT  阅读(112)  评论(0)    收藏  举报