sicily 1150 简单魔方 队列解题

1150. 简单魔板

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge

Description

魔板由8个大小相同方块组成,分别用涂上不同颜色,用1到8的数字表示。

其初始状态是

1 2 3 4

8 7 6 5

对魔板可进行三种基本操作:

A操作(上下行互换):

8 7 6 5

1 2 3 4

B操作(每次以行循环右移一个):

4 1 2 3

5 8 7 6

C操作(中间四小块顺时针转一格):

1 7 2 4

8 6 3 5

用上述三种基本操作,可将任一种状态装换成另一种状态。

Input

输入包括多个要求解的魔板,每个魔板用三行描述。

第一行步数N(不超过10的整数),表示最多容许的步数。

第二、第三行表示目标状态,按照魔板的形状,颜色用1到8的表示。

当N等于-1的时候,表示输入结束。

Output

对于每一个要求解的魔板,输出一行。

首先是一个整数M,表示你找到解答所需要的步数。接着若干个空格之后,从第一步开始按顺序给出M步操作(每一步是A、B或C),相邻两个操作之间没有任何空格。

注意:如果不能达到,则M输出-1即可。

Sample Input

4
5 8 7 6
4 1 2 3
3
8 7 6 5
1 2 3 4
-1

Sample Output

2 AB
1 A

评分:M超过N或者给出的操作不正确均不能得分。

Problem Source

ZSUACM Team Member

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

//定义一个魔方的结构体
typedef struct mf {
	int up; //魔方上行数字
	int down; //魔方下行数字
	char op; //由该操作得到该魔方
	int pre; //记录该魔方的前一个魔方,即在三叉树中的父节点在队列中的下标,用于回溯输出最短到达该目的魔方所经过的变换,此设计很关键
} MF;

//比较待插入的魔方是否已经在队列中存在
bool cmp(vector<MF> &mfs, MF mf, char op, int pre) {
	for (int i = 0; i < mfs.size(); i++) {
		if (mfs[i].up == mf.up && mfs[i].down == mf.down) { //如果队列中已经存在该待插入魔方,则不进行插入,即对三叉树进行剪枝
			return false;
		}
	}
	//队列中不存在该魔方,插入
	mf.pre = pre;
	mf.op = op;
	mfs.push_back(mf);
	return true;
}
//由于一共有三种操作,所以为三叉树
//操作A 1234 8765 -> 8765 1234 通过result引用来返回进行操作后的魔方
char opA(MF mf, int pre, MF &result) {
	int m = mf.up;
	int n = mf.down;
	mf.up = n;
	mf.down = m;
	result = mf;
	result.pre = pre;
	result.op = ‘A‘;
	return ‘A‘;
}

//操作B 1234 8765 -> 4123 5876
char opB(MF mf, int pre, MF &result) {
	int up_first = (mf.up % 10) * 1000;
	int down_first = (mf.down % 10) * 1000;
	int up_last = ((mf.up - (mf.up / 1000) * 1000) - ((mf.up - (mf.up / 1000) * 1000) / 100) * 100) / 10;
	int down_last = ((mf.down - (mf.down / 1000) * 1000) - ((mf.down - (mf.down / 1000) * 1000) / 100) * 100) / 10;
	mf.up = up_first + (mf.up / 1000) * 100 + ((mf.up - (mf.up / 1000) * 1000) / 100) * 10 + up_last;
	mf.down = down_first + (mf.down / 1000) * 100 + ((mf.down - (mf.down / 1000) * 1000) / 100) * 10 + down_last;
	result = mf;
	result.pre = pre;
	result.op = ‘B‘;
	return ‘B‘;
}

//操作C 1234 5678 -> 1624 5738
char opC(MF mf, int pre, MF &result) {
	int i1 = (mf.up - (mf.up / 1000) * 1000) / 100;
	int i2 = ((mf.up - (mf.up / 1000) * 1000) - i1 * 100) / 10;
	int j1 = (mf.down - (mf.down / 1000) * 1000) / 100;
	int j2 = ((mf.down - (mf.down / 1000) * 1000) - j1 * 100) / 10;
	mf.up = (mf.up / 1000) * 1000 + j1 * 100 + i1 * 10 + mf.up % 10;
	mf.down = (mf.down / 1000) * 1000 + j2 * 100 + i2 * 10 + mf.down % 10;
	result = mf;
	result.pre = pre;
	result.op = ‘C‘;
	return ‘C‘;
}

int main () {
	int max;

	while(cin >> max && max != -1) {
		int find_length = 0;
		int target[8];
		int value;

		for (int i = 0; i < 8; i++) {
			cin >> value;
			target[i] = value;
		}
		vector<MF> mfs;
		stack<char> ops;
		int fp = 0, rp = 0;//fp为头指针,指向当前正在处理的节点,rp为队列尾指针,指向入队的节点
		bool success = false;

		int up = target[0] * 1000 + target[1] * 100 + target[2] * 10 + target[3]; //目标魔方的上行
		int down = target[7] + target[6] * 10 + target[5] * 100 + target[4] * 1000; //目标魔方的下行 

		MF mf;
		mf.up = 1234;
		mf.down = 8765;
		mf.op = ‘ ‘;
		mf.pre = -1;
		mfs.push_back(mf);

    	//若未找到,则循环查找
		while (mfs[fp].up != up || mfs[fp].down != down) {

			//对魔方进行操作,头指针执行正在进行操作的魔方,尾指针执行操作后进入队列的魔方
			MF result;
			char a = opA(mfs[fp], fp, result);
			//每次进行一次变换后,查看是否为目标态
			if (result.up == up && result.down == down) {
			//发现目标魔方,则根据pre来回溯得到操作序列
				while (result.pre != -1) {
					ops.push(result.op);
					find_length++;
					result = mfs[result.pre];//回溯
				}
				success = true;
				break;
			} else if (cmp(mfs, result, a, fp)) {//如果队列中没有该魔方,该魔方进队
				rp++; //尾指针递增
			}

			char b = opB(mfs[fp], fp, result);
			if (result.up == up && result.down == down) {
			//发现目标魔方,则根据pre来回溯得到操作序列
				while (result.pre != -1) {
					ops.push(result.op);
					find_length++;
					result = mfs[result.pre];//回溯
				}
				success = true;
				break;
			} else if (cmp(mfs, result, b, fp)) {
				rp++;
			}

			char c = opC(mfs[fp], fp, result);
			if (result.up == up && result.down == down) {
			//发现目标魔方,则根据pre来回溯得到操作序列
				while (result.pre != -1) {
					ops.push(result.op);
					find_length++;
					result = mfs[result.pre];//回溯
				}
				success = true;
				break;
			}else if (cmp(mfs, result, c, fp)) {
				rp++;
			}
			fp++; //头指针递增
		}
        //如果不能在指定步数内找到,则输出-1
		if (find_length > max) {
			cout << -1 << endl;
		} else {
			cout << find_length << " ";
			while (!ops.empty()) { //找到输出由初态变为目标态的过程
				cout << ops.top();
				ops.pop();
			}
			cout << endl;
		}
	}

	return 0;
}

  

时间: 2024-10-29 14:50:03

sicily 1150 简单魔方 队列解题的相关文章

sicily 1151 简单魔方B BFS和哈希判断重复解题

1151. 魔板 Constraints Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge Description 题目和A题相同,在这里我们把数据范围扩大:N可能超过10. 请仔细考虑各种情况. Input 输入包括多个要求解的魔板,每个魔板用三行描述. 第一行步数N,表示最多容许的步数. 第二.第三行表示目标状态,按照魔板的形状,颜色用1到8的表示. 当N等于-1的时候,表示输入结束. Output 对于每一个要求解的魔板,输出一

Sicily 1150. 简单魔板

BFS.军训晚上下雨无聊写的水题. 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <queue> 6 #include <vector> 7 #define rep(i,l,r) for(int i = l; i <= r; i++) 8 #define clr(x,y) memse

Sicily 1308. Dependencies among J 解题报告

题目:1308. Dependencies among J 思路: 比较简单的一道题,要知道m最早完成的时间,只需要找出所有需要在m之前完成的工作,将它们的完成时间加起来即可.这里使用vector的数组存储每个结点的邻接点,从结点m开始,依次宽度优先搜索m的每个邻接点...数组visited记录每个结点是否被访问过,遇到已经访问过的结点直接跳过. 读取的时候一开始没有找到解决办法,要读取一行的数字,并且要判断是否换行,可以首先读取第一个数即完成时间,然后用getchar读取一个字符,如果是'\n

哈,又一款超级简单的队列(MQ)实现方案来了~

开源的消息队列已经很多了,但大部分很重,实际环境下,很多可能只是使用到了一点功能而已,杀鸡使用牛刀,着实有些浪费了.很多时候,我们只想要一片绿叶,但它们给了我们整个的春天,很难消化.本着DIR精神, 也琢磨了一个超级简单的队列实现. 说是超级简单,嗯,绝对是超级简单,队列的存储采用Redis进行持久化存储,采用Netty提供HTTP方式的队列的出/入.Redis的客户端采用的Jedis.然后呢,然后就没了啊. 一.Redis Redis内置订阅发布模型(Publish/Subscribe),其缺

C语言 简单的队列(数组队列)

//简单的队列 #include<stdio.h> #include<stdlib.h> #define datatype int #define N 10 //定义队列结构体 struct queue{ int front;//队头 int endline;//队尾 datatype data[N];//数据 }; typedef struct queue Queue; Queue myQueue = { 0, 0, { 0 } }; //初始化队列 void initQueue

简单消息队列服务 HTTPSQS

HTTPSQS(HTTP?Simple?Queue?Service)是一款基于 HTTP GET/POST 协议的轻量级开源简单消息队列服务,使用 Tokyo Cabinet 的 B+Tree Key/Value 数据库来做数据的持久化存储. 队列(Queue)又称先进先出表(First In First Out),即先进入队列的元素,先从队列中取出.加入元素的一头叫"队头",取出元素的一头叫"队尾".利用消息队列可以很好地异步处理数据传送和存储,当你频繁地向数据库

Java操作simple简单消息队列

1.进入官网 进入get start 然后进入Tutorials 发现简单消息队列 2. 原文地址:https://www.cnblogs.com/juncaoit/p/8570703.html

Redis实现简单消息队列

任务异步化 打开浏览器,输入地址,按下回车,打开了页面.于是一个HTTP请求(request)就由客户端发送到服务器,服务器处理请求,返回响应(response)内容. 我们每天都在浏览网页,发送大大小小的请求给服务器.有时候,服务器接到了请求,会发现他也需要给另外的服务器发送请求,或者服务器也需要做另外一些事情,于是最初们发送的请求就被阻塞了,也就是要等待服务器完成其他的事情. 更多的时候,服务器做的额外事情,并不需要客户端等待,这时候就可以把这些额外的事情异步去做.从事异步任务的工具有很多.

2016.8.27一套简单的题解题报告

一套不错的题,需要相关资料的联系我咯 考试分析: 1.  由于题目的名字加上第一道题没读完时我以为是我最不擅长的treeDP(其实不得不说,树和图上的题我真的是不想写,一般都写不对,上课太不认真,这个弱点要加强训练),我直接跳到了最后一道题,明知考3h还用了30min去分析,不过还是感谢,这30min救了我两道题出来: 这套题的确还是比较简单,后两道题只要认真分析数据都不会有问题,也许是因为暑假切了贪心和递推,我对分析数据比较在行,第三题切完之后还有2h,不过没写高精的我有点慌,打算最后留一点时