首页 > 其他分享 >NOJ 六数码问题(代码+详解)

NOJ 六数码问题(代码+详解)

时间:2023-11-21 15:11:06浏览次数:30  
标签:map arr 数字 NOJ carr 布局 数码 格中 详解

描述

现有一两行三列的表格如下:

A B C
D E F

把1、2、3、4、5、6六个数字分别填入A、B、C、D、E、F格子中,每个格子一个数字且各不相同。每种不同的填法称为一种布局。如下:

1 3 5
2 4 6
布局1

2 5 6
4 3 1
布局2

定义α变换如下:把A格中的数字放入B格,把B格中的数字放入E格,把E格中的数字放入D格,把D格中的数字放入A格。
定义β变换如下:把B格中的数字放入C格,把C格中的数字放入F格,把F格中的数字放入E格,把E格中的数字放入B格。

问:对于给定的布局,可否通过有限次的α变换和β变换变成下面的目标布局:

1 2 3
4 5 6
目标布局

输入

本题有多个测例,每行一个,以EOF为输入结束标志。每个测例的输入是1到6这六个数字的一个排列,空格隔开,表示初始布局ABCDEF格中依次填入的数字。

输出

每个输出占一行。可以转换的,打印Yes;不可以转换的,打印No。

输入样例

1 3 5 2 4 6
2 5 6 4 3 1

输出样例

No
Yes

题解

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

// 定义一个布局的结构体,方便下面入队,变换等操作
typedef struct arr {
	int a, b, c, d, e, f;
}arr;
arr s;
queue <arr> q;

int map[654321];
void func1(arr* carr); // α变换
void func2(arr* carr); // β变换
bool hashx(arr x); // 判断布局x是否被搜过
int bfs();

int main()
{
	while (scanf("%d%d%d%d%d%d", &s.a, &s.b, &s.c, &s.d, &s.e, &s.f) != EOF)
	{
		memset(map, 0, sizeof(map));
		// 先将初始布局入队,并标记为1
		q.push(s);
		map[s.f + s.e*10 + s.d * 100 + s.c*1000 + s.b*10000 + s.a*100000 - 123456] = 1;
		if (bfs())
			cout << "Yes" << endl;
		else
			cout << "No" << endl;
		// 最后需要清空队列
		while (!q.empty())
			q.pop();
	}
}

void func1(arr* carr)
{
	swap(carr->a, carr->b);
	swap(carr->a, carr->e);
	swap(carr->a, carr->d);
}

void func2(arr* carr)
{
	swap(carr->b, carr->c);
	swap(carr->b, carr->f);
	swap(carr->b, carr->e);
}

bool hashx(arr x)
{
	int ans = x.f + x.e*10 + x.d * 100 + x.c*1000 + x.b*10000 + x.a*100000 - 123456;
	// 若被没被搜过,标记1,返回true
	if (map[ans] == 0)
	{
		map[ans] = 1;
		return true;
	}
	// 否则返回false
	else
		return false;
}

int bfs()
{
	//当前布局 α布局  β布局
	arr carr, acarr, bcarr;
	while(!q.empty())
	{
		// 如果目标布局被搜过
		if (map[0] == 1)
		{
			return 1;
		}
		// 从队列中取出
		carr = q.front();
		q.pop();
		// α变换
		acarr = carr;
		func1(&acarr);
		// β变换
		bcarr = carr;
		func2(&bcarr);
		// 如果没有被搜过,则入队
		if (hash(acarr))
		{
			q.push(acarr);
		}
		if (hash(bcarr))
		{
			q.push(bcarr);
		}
	}
	// 队列都搜完也没搜到,返回0
	return 0;
}

标签:map,arr,数字,NOJ,carr,布局,数码,格中,详解
From: https://www.cnblogs.com/hello33mao/p/17846564.html

相关文章

  • Spring5学习随笔-事务属性详解(@Transactional)
    学习视频:【孙哥说Spring5:从设计模式到基本应用到应用级底层分析,一次深入浅出的Spring全探索。学不会Spring?只因你未遇见孙哥】第三章、Spring的事务处理1.什么是事务?事务是保证业务操作完整性的一种数据库机制事务的4特点:ACIDA原子性C一致性I隔离性D持久性2.如何......
  • 程序地址空间详解(6千字长文)
    程序地址空间C/C++地址空间!在先认识程序地址空间前我们要先认识一下C/C++的地址空间!这就是C/C++的地址空间的结构!不过这个地址空间究竟是什么?——是内存吗?==答案是错误的!这个地址空间其实不是内存!==我们可以看一下intmain(){pid_tid=fork();if(id<0)......
  • 7段数码管绘制
    importturtleimportdatetimeimporttimedefdraw_gap():#画数码间隔turtle.penup()turtle.fd(5)defdraw_line(draw):#画单段数码管draw_gap()turtle.pendown()ifdrawelseturtle.penup()turtle.fd(40)draw_gap()turtle.r......
  • 7段数码管绘制
       ......
  • 7段数码管绘制
    importturtle,datetimedefdrawGap():#绘制数码管间隔turtle.penup()turtle.fd(5)defdrawLine(draw):#绘制单段数码管drawGap()turtle.pendown()ifdrawelseturtle.penup()turtle.fd(40)drawGap()turtle.right(90)defdrawDigit(d):#......
  • RK3588-MPP解码详解
    一.简介[RK3588从入门到精通]专栏总目录本篇文章进行RK3588-MPP解码的详细解析二.环境介绍硬件环境:ArmSoM-W3RK3588开发板软件版本:OS:ArmSoM-W3Debian11三.解码器数据流接口3.1decode_put_packet输入码流的形式:分帧与不分帧MPP的输入都是没有封装......
  • CSP: Content-Security-Policy详解应对XSS攻击
    https://www.jianshu.com/p/74ea9f0860d2 CSP:Content-Security-Policy详解 前言跨域脚本攻击(XSS)是最常见、危害最大的网页安全漏洞。为了防止它,要采取很多编程措施(比如大多数人都知道的转义、过滤HTML)。很多人提出,能不能根本上解决问题,即浏览器自动禁止外部注入恶意脚......
  • Linux中execl函数详解与日常应用!
    Linux中execl函数详解与日常应用execl是Linux系统中的一个系统调用,用于执行指定路径下的可执行文件。本文将详细介绍execl函数的使用方法和参数含义,并探讨其在日常开发中的常见应用场景和注意事项。1.execl函数概述execl函数属于Linux系统调用之一,其原型为:intexecl(constc......
  • 7段数码管绘制
    importturtleimportdatetimeimporttimedefdraw_gap():#绘制数码间隔turtle.penup()turtle.fd(5)defdraw_line(draw):#绘制单段数码管draw_gap()turtle.pendown()ifdrawelseturtle.penup()turtle.fd(40)draw_gap()turtle.right(90)def......
  • 7段数码管绘制
    要求:画出,系统时间。具体包括:小时,分,秒,星期。 importturtleastimporttimea=time.strftime('%a',time.localtime())ifa=='Mon':c=1elifa=='Tue':c=2elifa=='Wed':c=3elifa=='Thu':c=4elif......