WOJ132Squares(BFS+打表)

上来拿个1<<10勋章…


题目链接woj132


Description

Consider a 3 by 3 arrangement of the digits 1 to 9, as illustrated in the following diagram:
1 3 5
8 7 6
4 9 2
Figure 1
The arrangement can by modified by rotating any of the 2-by-2 groups in the corners, either clockwise or anticlockwise. Thus if the top-right
corner of the above arrangement is rotated anticlockwise, the result is the following arrangement:
1 5 6
8 3 7
4 9 2
Figure 2
A magic square is an n-by-n arrangement of numbers, such that the sum of the numbers in each row, column, and diagonal is the same. For
example, the following diagram illustrates one possible 3-by-3 magic square for the numbers 1 to 9:
8 1 6
3 5 7
4 9 2
Figure 3
Your task is to determine the minimum number of moves to trans-form a given digit arrangement into a magic square.
For example, the magic square in Figure 3 can be obtained from the arrangement illustrated in Figure 2 by one clockwise rotation of the top-
left corner. Thus the arrangement given in Figure 1 can be transformed into a magic square in 2 moves (and, as you can verify, no shorter
sequences of moves would suffice).


Input

Input will consist of a series of lines, each specifying an initial arrangement of the digits 1 to 9, listed in row-by-row order. The end of
the input is indicated by a line that consists of the word END.

Output

Output for each arrangement should consist of either:

  1. The minimum number of moves followed by a single space and then the word “moves”, or
  2. The word “IMPOSSIBLE”, if it is not possible to achieve a magic square arrangement.

Sample Input

135876492
438975261
672159834
129764583
END

Sample Output

2 moves
1 moves
0 moves
4 moves


题目大意:给一个三阶矩阵,问能不能通过旋转任意一个二阶子阵(注意是相邻),经过若干次旋转得到一个三阶幻方。


题目思路:三阶幻方有8种,由于9个数字的全排列规模在3e5左右,显然合法的能到达幻方状态的个数必然小于这个规模,于是可以bfs处理一张表处理,然后通过查表解答。由于bfs的性质,最早生成的状态一定是最优解,比如某个状态可以由两种幻方转出来,但他存的步数一定是最先生成他的那个步数,后面形成的一定没前面的优秀。


Code

#include <bits/stdc++.h>
using namespace std;

int Max;
long long res;
unordered_map<long long, long long> vis;
queue<pair<long long, int> > q;
long long st[8] = {492357816,294753618,834159672,438951276,618753294,816357492,276951438,672159834};
int op[4][4] = {
	0,3,4,1,
	1,4,5,2,
	3,6,7,4,
	4,7,8,5
};

void add(long long now, int op[4], int step) {
	long long arr1[9], arr2[9];
	for(int i=0; now!=0; i++) {
		arr2[8-i]=arr1[8-i]= now % 10;
		now /= 10;
	}
	
	long long tmp = arr1[op[3]];
	for(int i=3; i>=1; i--) arr1[op[i]] = arr1[op[i-1]];
	arr1[op[0]] = tmp;
	
	tmp = arr2[op[0]];
	for(int i=0; i<=2; i++) arr2[op[i]] = arr2[op[i+1]];
	arr2[op[3]] = tmp;
	
	long long cur1=0, cur2=0;
	for(int i=8; i>=0; i--) {
		cur1 = cur1*10 + arr1[i];
		cur2 = cur2*10 + arr2[i];
	}
	if(!vis.count(cur1)) {
		q.push(make_pair(cur1, step));
		vis.insert(make_pair(cur1, step));
	}
	if(!vis.count(cur2)) {
		q.push(make_pair(cur2, step));
		vis.insert(make_pair(cur2, step));
	}
}

void bfs() {
	vis.clear();
	while(!q.empty()) q.pop();
	for(int i=0; i<8; i++) q.push(make_pair(st[i], 0)), vis.insert(make_pair(st[i], 0));
	while(!q.empty()) {
		pair<long long, int> cur = q.front(); q.pop();
		for(int i=0; i<4; i++) add(cur.first, op[i], cur.second+1);
	}
}

int main() {
	string cmd;
	bfs();
	while(cin >> cmd && cmd[0]!='E') {
		res = 0;
		for(int i=0; i<9; i++) res = res*10 + (cmd[i]-'0');
		if(!vis.count(res))
			cout << "IMPOSSIBLE" << endl;
		else
			cout << vis[res] << " moves" << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值