算法竞赛入门经典:第七章 暴力求解法 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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算法竞赛(第6章) - c 与stl基础二:栈stack与前中后缀表达式的应用 在竞赛中,算法和数据结构是非常重要的。栈(stack)是一种常用的数据结构,具有先进后出(LIFO)的特性,它在解决一些问题时具有很大的帮助。 栈在数学表达式计算中有广泛的应用。一个常见的应用是将中缀表达式转换为后缀表达式,这样可以更方便地进行计算。中缀表达式是我们通常使用的表达式形式,例如 2 + 3 * 4。而后缀表达式是一种更加简洁的表达式形式,例如 2 3 4 * +。 转换过程中,我们使用到了栈。我们按照运算符的优先级依次扫描中缀表达式的每个元素,如果是操作数,就直接输出到后缀表达式中;如果是运算符,则将其与栈顶元素进行比较,如果优先级大于等于栈顶元素,则将其入栈,否则将栈顶元素出栈并输出到后缀表达式中,然后再将当前运算符入栈。最后,将栈中剩余的运算符依次出栈并输出到后缀表达式中。 转换完成后,我们可以使用栈来计算后缀表达式。遍历后缀表达式的每个元素,如果是操作数,则将其入栈;如果是运算符,则将栈顶的两个元素出栈并进行相应的运算,然后将结果入栈。最后,栈中的元素即为计算后的结果。 除了中缀转后缀表达式之外,栈还有其他的应用。例如,我们可以使用栈判断一个括号序列是否合。当遇到左括号时,就将其入栈,当遇到右括号时,就将其与栈顶的元素进行匹配,如果匹配成功,则将栈顶元素出栈,否则,表示括号序列不合。 总的来说,栈是一个非常常用的数据结构,有广泛的应用。在竞赛中,熟练掌握栈的方和技巧,能够帮助我们更好地解决一些问题,提高编程的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值