Tyvj 八数码



P1541 - 八数码

From  admin     Normal (OI)
总时限:16s    内存限制:128MB    代码长度限制:64KB
背景 Background
 Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
描述 Description
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。 
输入格式 InputFormat
输入初试状态,一行九个数字,空格用0表示
输出格式 OutputFormat
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例输入 SampleInput [复制数据]
283104765
样例输出 SampleOutput [复制数据]
4
注意判重的方法
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<string>
#include<queue>
#define MAX 1000003
#define Max 100003
using namespace std;
string goal = "123804765";
int dir[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
struct node{
	int x, y, z,step;
	string num;
};
int c;
int key[MAX], head[MAX], Next[MAX];
node start;
int step,number;
void Init(){
	memset(head, -1, sizeof(head));
	memset(Next, 0, sizeof(Next));
}
int Hash(string &cont){
	number = 0;
	for (int i = 0; i<9; i++){
		number =number*10+ cont[i]-'0';
	}
	return number%MAX;
}
void Add(string &cont){
	int h = Hash(cont);
	key[c] = number;
	Next[c] = head[h];
	head[h] = c;
	c++;
}
int Find(string &cont){
	int h = Hash(cont);
	for (int i = head[h]; i != -1; i = Next[i]){
		if (key[i] == number){
			return 1;
		}
	}
	return 0;
}
/*struct hashNode{
	string num;
	hashNode *next;
};
struct hashHead{
	hashNode *head;
};
hashHead HashHead[MAX];

int Find(string &cont){
	int h = Hash(cont);
	hashNode *temp = HashHead[h].head;
	while (temp){
		if (temp->num == cont){
			return 1;
		}
		temp = temp->next;
	}
	return 0;
}
int Build_Hash(string &cont){
	int h = Hash(cont);
	if (Find(cont))
		return 0;
	else {
		hashNode *HashNode = new hashNode;
		HashNode->next = HashHead[h].head;
		HashNode->num = cont;
		HashHead[h].head = HashNode;
		return 1;
	}
}*/
void bfs(){
	queue<node>q;
	q.push(start);
	while (!q.empty()){
		node temp = q.front();
		q.pop();
		if (temp.num == goal){
			cout << temp.step << endl;
			return ;
		}
		Add(temp.num);
		for (int i = 0; i < 4; i++){
			int nx = temp.x + dir[i][0];
			int ny = temp.y + dir[i][1];
			int nz = 3 * nx + ny;
			string tp = temp.num;
			if (nx >= 0 && ny >= 0 && nx < 3 && ny < 3){
				char ch = tp[temp.z];
				tp[temp.z] = tp[nz];
				tp[nz] = ch;
				if (!Find(tp)){
					Add(tp);
					node newnode;
					newnode.num = tp, newnode.x = nx, newnode.y = ny;
					newnode.z = nz; newnode.step = temp.step+1;
					q.push(newnode);
				}
			}
		}
	}
}
int main(){
	Init();
	string s; cin >> s; start.num = s;
	for (int i = 0; i < s.length(); i++){
		if (s[i] == '0'){
			start.x = i / 3, start.y = i % 3;
			start.z = i;
		}
	}
	bfs();
	//system("pause");
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值