NPU 程序设计17届 1045 六数码问题

Problem E

六数码问题

时限:1000ms 内存限制:10000K 总时限:3000ms

描述:

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

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

本题的主要难点在于,如何将六数码图的数据储存起来。经过查阅资料,以及之前在课上八皇后用一维数组储存数据、用二进制的双精度数(100001000....)储存真值表,发现本题的数据可以用一个变量储存在队列内。如2 5 6/n 4 3 1/n,我们可以直接用256431储存。由于本身六数码图每个位置有特定的顺序,我们可以很容易将这个储存用的变量还原为六数码图。

#include
#include
#include
#include

using namespace std;

queue q;//数组可以储存当前6数码图的形态 
map used;
//map函数用来一一对应每一种可能出现的6数码图情况并标记已被使用 

void init(int num);
int bfs();
int change(int u,int i);

int main()
{
	int first,num,i,result;
	while (scanf("%d",&first)!=EOF)
	{//如果没有输入则结束程序 
		num = first;//将第一个输入的数放入 
		for (i = 0;i < 5;i++)
		{//先乘10,再将新输入的数加进去,形成我们想要的储存形式 
			num = num * 10; 
			cin >> first;
			num = num + first;
		}
		
		while (!q.empty())
		{
			q.pop();
		}
		used.clear();
		//每次使用前先将map清空防止干扰 
		init(num);
		result = bfs();
		if (result == 1)
		{
			cout << "Yes" << endl;
		}
		else if (result == 0)
		{
			cout << "No" << endl;
		}
	}
	return 0;
}

void init(int num)
{//将初始的情况放入数组并标记已使用 
	q.push(num);
	used[num] = 1; 
}

int bfs()
{
	int u,v,i;
	while (!q.empty())
	{
		u = q.front();
		q.pop();
		for (i = 0;i < 2;i++)
		{
			v = change(u,i);
			if (v == 123456)
			{//如果等于我们想要的情况,返回1 
				return 1;
			}
			else if (v != 123456 && used[v] != 1)
			{//将经过变换得到的图放入队列并标记 
				q.push(v);
				used[v] = 1;
			}
		}
	}//如果所有经过α,β变换生成的图都不符合要求,则返回0 
	return (0);
}

int change(int u,int i)
{
	int nowmap[2][3],j,k,num;
	int newmap[2][3];
	//将储存在一个变量的数据恢复为6数码的二维数组形态 
	for (j = 1;j >= 0;j--)
	{
		for (k = 2;k >= 0;k--)
		{
			num = u % 10;
			nowmap[j][k] = num;
			newmap[j][k] = num;
			u = u / 10;
		}
	}
	if (i == 0)
	{//α变换 
		newmap[0][0] = nowmap[1][0];
		newmap[0][1] = nowmap[0][0];
		newmap[1][1] = nowmap[0][1];
		newmap[1][0] = nowmap[1][1];
	}
	if (i == 1)
	{//β变换 
		newmap[0][1] = nowmap[1][1];
		newmap[0][2] = nowmap[0][1];
		newmap[1][2] = nowmap[0][2];
		newmap[1][1] = nowmap[1][2];		
	}
	num = 0;
	//将变换后的二维数组储存在一个变量内 
	for (j = 0;j < 2;j++)
	{
		for (k = 0;k < 3;k++)
		{
			num = num * 10;
			num = num + newmap[j][k];
		}
	}
	return (num);
}

你可能感兴趣的:(学习记录,C语言基础,二维数组,初学,广搜)