sicily 1150. 简单魔板 & 1151. 魔板

典型的广搜题目:

1)       首先把初始状态所代表的节点压入队列,初始节点的状态为12348765,父节点位置为-1(表示没有父节点),op为空,表示没有操作,标记初始节点的状态已访问,初始化step(表示当前搜索的层次)为0;

2)       当队列不为空(head< tail),一直循环以下步骤;

3)       用一个curTail记录当前队列的队尾,这表示了从head到curTail为层次为step的这一层,对这一层的节点进行扩展。

4)       对于当前这一层的所有节点,首先判断它的状态是否为目标状态,如果是表示找到了结果,标记成功并且输出路径,退出。如果不是目标状态,则分别按照A、B、C三个操作来扩展,如果扩展之后的节点状态是以前没有达到过的,那么就压入队列(tail++),并且标记该状态已访问(对于每一个状态可以通过康托展开来做hash,使得一个节点映射为一个更小的整数)。

5)       当前整一层访问完毕,step++,如果step大于了输入的N,则退出,表示没有完成任务。

6)       如果step不大于输入的N,表示搜索没有结束,转到第2)步继续进行。

#include <cstdio>
#include <cstring>

int fact[] = {1, 1, 2, 6, 24, 120, 720, 5040};
bool vis[40500];

struct Node
{
	int state, p;
	char op;
}que[40500];

int op(int state, int c)//三步操作
{
	int res = 0;
	switch(c)
	{
	case 1:
		res = state/10000 + state%10000*10000;
		break;
	case 2:
		res = state/10000%10*10000000 + state/100000*10000
			+state%10*1000 + state/10%1000;
		break;
	case 3:
		res = state/10000000*10000000 + state/100%10*1000000 
			+ state/1000000%10*100000 + state/10000%10*10000
			+ state/1000%10*1000 + state/10%10*100
			+ state/100000%10*10 + state%10;
		break;
	}
	return res;
}

int hash(int state)//康托展开
{
	char str[10];
	int res = 0;
	sprintf(str, "%d", state);
	for(int i=0; i<8; i++)
	{
		int cnt = 0;
		for(int j=i+1; j<8; j++)
			if(str[i] > str[j])	cnt++;
		res += cnt*fact[7-i];
	}
	return res;
}

void print(int p)//打印路径
{
	if(p != -1)
	{
		print(que[p].p);
		printf("%c", que[p].op);
	}
}

int main()
{
	int M, startState = 12348765;
	while(scanf("%d", &M), M != -1)
	{
		int endState = 0, val, step = 0, head = 0, tail = 1;
		bool hasfinished = false;

		for(int i=0; i<8; i++)
		{
			scanf("%d", &val);
			endState = endState*10 + val;
		}
		memset(vis, false, sizeof(vis));
		que[0].state = startState, que[0].p = -1;
		vis[hash(startState)] = true;

		while(head < tail && !hasfinished)//队列不为空,或者搜索还未结束,继续
		{
			int curTail = tail;//curTail为测试为step的这一层的最后一个节点的位置
			while(head < curTail)
			{
				int curState = que[head++].state;
				if(curState == endState)
				{
					printf("%d ", step);
					print(head-1);
					printf("\n");
					hasfinished = true;
					break;
				}
				for(int i=1; i<=3; i++)
				{
					int tmp = op(curState, i);
					int tmpHash = hash(tmp);
					if(!vis[tmpHash])
					{
						vis[tmpHash] = true;
						que[tail].state = tmp, que[tail].p = head - 1, que[tail++].op = (char)(i- 1+'A');
					}
				}
			}
			step++;//搜索层次加一
			if(step > M)	break;
		}
		if(!hasfinished)	printf("-1\n");
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值