算法竞赛入门经典:第七章 暴力求解法 7.20八数码问题之stl

/*
八数码问题之stl:
1set<State> vis,这样只需要调用if(vis.count(s))来判断s是否在集合vis中,并用vis.insert(s)加入集合,用vis.remove(s)从集合中移除s。
问题:并不是所有类型的State都可以作为set中的元素类型。set的元素必须定义"<"运算符,C语言原生的数组(包括字符数组)却不行。

2如果数组不能转化为整数,自己声明结构体,重载函数调用符比较状态。下面中,整数a和b分别是两个状态在状态数组st中的下标,在比较时直接使用memcpy来比较整个
内存块

输入:
2 6 4 1 3 7 0 5 8
8 1 5 7 3 6 4 0 2
输出:
31
*/

/*
关键:
1set<State> vis,这样只需要调用if(vis.count(s))来判断s是否在集合vis中,并用vis.insert(s)加入集合,用vis.remove(s)从集合中移除s。
问题:并不是所有类型的State都可以作为set中的元素类型。set的元素必须定义"<"运算符,C语言原生的数组(包括字符数组)却不行。

2如果数组不能转化为整数,自己声明结构体,重载函数调用符比较状态。下面中,整数a和b分别是两个状态在状态数组st中的下标,在比较时直接使用memcpy来比较整个
内存块。
typedef struct Cmp
{
	bool operator()(int iIndexA,int iIndexB) const//注意,容器中的比较函数用的是重载函数调用操作符,本质上仍然是比较操作

3 int memcmp(const void* buf1,const void* buf2,size_t count)


*/

#include <stdio.h>
#include <string.h>
#include <set>

using namespace std;
#define MAXSIZE 1000000
typedef int State[9];
State st[MAXSIZE],stEnd;
int iDist[MAXSIZE];
set<int> setState;//这里穿入的是哈希值
int go[][2] = 
{
	-1,0,
	1,0,
	0,-1,
	0,1
};

typedef struct Cmp
{
	bool operator()(int iIndexA,int iIndexB) const//注意,容器中的比较函数用的是重载函数调用操作符,本质上仍然是比较操作
	{
		return memcmp(&st[iIndexA],&st[iIndexB],sizeof(st[iIndexB])) < 0 ;
	}
}Cmp;


set<int,Cmp> setState2;

void init2()
{
	setState2.clear();
}

bool isInsert2(int iIndex)
{
	if(setState2.count(iIndex))
	{
		return false;
	}
	else
	{
		setState2.insert(iIndex);
		return true;
	}
}

void init()
{
	setState.clear();
}

bool isInsert(int iNum)
{
	int iSum = 0;
	for(int i = 0 ; i < 9; i++)
	{
		iSum = iSum * 10 + st[iNum][i];
	}
	if(setState.count(iSum))
	{
		return false;
	}
	else
	{
		setState.insert(iSum);
		return true;
	}
}

int bfs()
{
	int iFront = 1,iRear = 2;
	init2();
	while(iFront < iRear)
	{
		State& state = st[iFront];
		if(memcmp(stEnd,state,sizeof(state)) == 0)
		{
			return iFront;
		}
		int iX,iY,iZ;
		for(iZ = 0; iZ < 9 ; iZ++)
		{
			if(!state[iZ])//这里不是st[iZ]
			{
				break;
			}
		}
		iX = iZ / 3;
		iY = iZ % 3;
		for(int i = 0 ; i < 4 ; i++)
		{
			int iNewX = iX + go[i][0];
			int iNewY = iY + go[i][1];
			int iNewZ = iNewX * 3 + iNewY;
			if(iNewX < 3 && iNewX >= 0 && iNewY < 3 && iNewY >= 0)
			{
				State& newState = st[iRear];
				//memcpy(newState,state,sizeof(state));
				memcpy(&newState,&state,sizeof(state));
				newState[iNewZ] = state[iZ];
				newState[iZ] = state[iNewZ];
				iDist[iRear] = iDist[iFront] + 1;
				if(isInsert2(iRear))
				{
					iRear++;
				}
			}
		}
		iFront++;
	}
	return -1;
}

void process()
{
	iDist[1] = 0;
	for(int i = 0 ; i < 9; i++)
	{
		scanf("%d",&st[1][i]);
	}
	for(int j = 0; j < 9; j++)
	{
		scanf("%d",&stEnd[j]);
	}
	int iRes = bfs();
	if(iRes > 0)
	{
		printf("%d\n",iDist[iRes]);
	}
	else
	{
		printf("-1\n");
	}
}

int main(int argc,char* argv[])
{
	process();
	system("pause");
	return 0;
}

你可能感兴趣的:(算法竞赛)