sicily 1151 魔板

7 篇文章 0 订阅

1151. 魔板

Constraints

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

Description

题目和A题相同,在这里我们把数据范围扩大:N可能超过10

请仔细考虑各种情况。

Input

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

第一行步数N,表示最多容许的步数。

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

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

Output

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

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

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

Sample Input

45 8 7 64 1 2 338 7 6 51 2 3 4-1

Sample Output

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

Problem Source

ZSUACM Team Member


#include<iostream>
#include<queue>
#include<string>
#include<memory h="">
using namespace std;

//利用康托展开,请先自行百度简单了解一下。

// 记录0-7的阶乘
int fac[8] = { 1, 1, 2, 6, 24, 120, 720, 5040 };
// 构造一个visit数组,来记录新节点是否在之前已经访问过。 总共有8!=40320种情况
bool visit[40321];

struct node {
	// 魔板上行
	int x;
	// 魔板下行
	int y;
	// 已经进行的操作次数
	int count;
	// 操作序列
	string step;
	node() {
		x = y = count = 0;
		step = "";
	}
	node(int x1, int y1, int a, string b) :x(x1), y(y1), count(a), step(b) {}
};

int init() {
	int a = 0, b;
	for (int i = 0; i < 4; i++) {
		cin >> b;
		a = a * 10 + b;
	}
	return a;
}

// 获取新得到的节点的康托编码。(也即这个状态对应的数组下标)
int getcode(node top) {
	int i = 7, k = 3;
	int n = 0;
	int a[8];
	for (int j = 3; j >= 0; j--) {
		a[i--] = top.y % 10;
		a[k--] = top.x % 10;
		top.y /= 10;
		top.x /= 10;
	}
	// 当前 未出现 的元素中是排在第几个
	for (int i = 0; i < 8; i++) {
		int count = 0;
		for (int j = i + 1; j < 8; j++) {
			if (a[i] > a[j]) {
				count++;
			}
		}
		n += count * fac[7 - i];
	}
	return n;
}

void way(node top, int i, queue<node>& q) {
	node newnode;
	newnode.count = top.count + 1;
	if (i == 0) {
		newnode.x = top.y;
		newnode.y = top.x;
		newnode.step = top.step +  "A";
		
	}
	else if (i == 1) {
		newnode.x = top.x % 10 * 1000 + top.x / 10;
		newnode.y = top.y % 10 * 1000 + top.y / 10;
		newnode.step = top.step + "B";
	}
	else {
		int hx = top.x / 100 % 10;
		int tx = top.x / 10 % 10;
		int hy = top.y / 100 % 10;
		int ty = top.y / 10 % 10;
		newnode.x = top.x / 1000 * 1000 + hy * 100 + hx * 10 + top.x % 10;
		newnode.y = top.y / 1000 * 1000 + ty * 100 + tx * 10 + top.y % 10;
		newnode.step = top.step + "C";
	}
	//判断新节点是否已经被访问过。没访问过,加入队列。
	if (visit[getcode(newnode)] == false) {
		visit[getcode(newnode)] = true;
		q.push(newnode);
	}
}


int main() {
	int maxstep;
	int x1 = 1234;
	int y1 = 8765;
	cin >> maxstep;
	while (maxstep != -1) {
		int flag = 1;
		int endx = init();
		int endy = init();
		memset(visit, false, sizeof(visit));
		visit[0] = true;
		queue<node> q;
		node start(x1, y1, 0, "");
		q.push(start);
		node top;
		while (1) {
			if (q.empty()) {
				flag = 0;
				break;
			}
			top = q.front();
			q.pop();
			if (top.count > maxstep) {
				flag = 0;
				break;
			}
			if (top.x == endx && top.y == endy) {
				break;
			}
			// 对于从队列中取出的节点进行三种操作
			for (int i = 0; i < 3; i++) {
				way(top, i, q);
			}
		}
		if (flag == 0) {
			cout << "-1" << endl;
		}
		else {
			cout << top.count << " " << top.step << endl;
		}
		cin >> maxstep;
	}
	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值