poj 1077 八数码问题 + 康托展开 + bfs

新年第一题,拖了这么久才做掉。

//============================================================================
//
// >     File        :    poj1077.cpp
// >     Author      :    flowertree
// >     Time        :    2016年1月16日
// >     Algorithm   :    八数码问题 + 康托展开 + bfs
//
//============================================================================

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;

#define MAX 1000005

struct node 
{
	int num[10];
	int position;
	char path[50];
};

int a[10] = {0, 1, 1, 2, 6, 24, 120, 720, 5040, 40320};
bool flag[MAX];
int aim = 46233;		//123456780 对应 康托展开的 hash值
int beginnum[10];
node n;
int beginposition;
int Move[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
char m[5] = {"rldu"};

int kt(int *x)		//康托展开对应全排列的hash值
{
	int sum = 0;
	for(int i = 1; i <= 9; i++)
	{
		int s = 0;
		for(int j = i + 1; j <= 9; j++)
			if(x[j] < x[i])
				s++;
		sum += s * a[10 - i];
	}
	return sum;
}

bool bfs()
{
	n.position = beginposition;
	int t = kt(n.num);
	if(t == aim)
	{
		printf("\n");
		return true;
	}
	flag[t] = true;
	strcpy(n.path, "\0");
	queue<node> q;
	q.push(n);
	while(!q.empty())
	{
		node temp = q.front();
		q.pop();
		int x, y;
		int tempx, tempy;
		if(temp.position % 3 == 0)
		{
			x = temp.position / 3;
			y = 3;
		}
		else
		{
			x = temp.position / 3 + 1;
			y = temp.position % 3;
		}
		node p;
		for(int j = 0; j < 4; j++)
		{
			tempx = x + Move[j][0];
			tempy = y + Move[j][1];
			if(tempx < 1 || tempx > 3 || tempy < 1 || tempy > 3)
				continue;
			for(int i = 0; i < 10; i++)
				p.num[i] = temp.num[i];
			int newposition = (tempx - 1) * 3 + tempy;
			int jiaohuan = p.num[newposition];
			p.num[newposition] = p.num[temp.position];
			p.num[temp.position] = jiaohuan;
			jiaohuan = kt(p.num);
			if(flag[jiaohuan])
				continue;
			if(jiaohuan == aim)
			{
				strcpy(p.path, temp.path);
				int len = strlen(temp.path);
				p.path[len] = m[j];
				p.path[len + 1] = '\0';
				cout << p.path << endl;
				return true;
			}
			flag[jiaohuan] = true;
			p.position = newposition;
			strcpy(p.path, temp.path);
			int len = strlen(temp.path);
			p.path[len] = m[j];
			p.path[len + 1] = '\0';
			q.push(p);
		}
	}
	return false;
}

int main()
{
	memset(flag, false, sizeof(flag));
	char temp;
	for(int i = 1; i <= 9; i++)
	{
		cin >> temp;
		if(temp == 'x')
		{
			beginposition = i;
			temp = '0';
		}
		n.num[i] = temp - '0';
	}
	bool mark = bfs();
	if(!mark)
		cout << "unsolvable" << endl;
	system("pause");
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值