1. 程式人生 > >UVA1343 The Rotation Game

UVA1343 The Rotation Game

題目大意

如圖所示形狀的棋盤上分別有8個1、2、3,要往A~H方向旋轉棋盤,使中間8個方格數字相同。圖(a)進行A操作後變為圖(b),再進行C操作後變為圖(c),這正是一個目標狀態(因為中間8個方格數字相同)。要求旋轉次數最少。如果有多解,操作序列的字典序應儘量小。

題目解析

本題是一個典型的狀態空間搜尋問題。本題採用IDEA*演算法,詳見程式碼。

#include<cstdio>
#include<algorithm>
using namespace std;
/*
	  	  A 0    B 1  
	      00    01
	      02    03
H 7	04 05 06 07 08 09 10 C 2
	      11    12
G 6	13 14 15 16 17 18 19 D 3
	      20    21
	      22    23
 		  F 5	E 4
 */
int line[8][7] = {
	{0, 2, 6, 11, 15, 20, 22}, 	//A
	{1, 3, 8, 12, 17, 21, 23}, 	// B
	{10, 9, 8, 7, 6, 5, 4},    	//C
	{19, 18, 17, 16, 15, 14, 13}//D
};
int rev[] = {5, 4, 7, 6, 1, 0, 3, 2};
const int center[] = {6, 7, 8, 12, 17, 16, 15, 11};
int a[25];
char ans[1100];
bool isFinal(){
	for(int i = 1; i < 8; ++i)
		if(a[center[i]] != a[center[0]]) return false;
	return true;
}
inline void move(int i){
	int temp = a[line[i][0]];
	for(int j = 0; j < 6; ++j)
		a[line[i][j]] = a[line[i]][j + 1];
	a[line[i][6]] = temp;
}
int diff(int target){
	int cnt = 0;
	for(int i = 0; i < 8; ++i)
		if(a[center[i]] != target) ++cnt;
	return cnt;
}
inline int h(){
	return min(min(diff(1), diff(2)), diff(3));
}
bool dfs(int d, int maxd){
	if(isFinal()){
		ans[d] = '\0';
		printf("%s\n", ans);
		return true;
	}
	if(h() + d > maxd) return false;
	for(int i = 0; i < 8; ++i){
		ans[d] = 'A' + i;
		move(i);
		if(dfs(d + 1, maxd)) return true;
		move(rev[i]);
	}
	return false;
}
int main(){
	for(int i = 4; i < 8; ++i)
		for(int j = 0; j < 7; ++j) line[i][j] = line[rev[i]][6 - j];
	while(scanf("%d", &a[0]) == 1 && a[0]){
		for(int i = 1; i < 24; ++i) scanf("%d", &a[i]);
		for(int i = 0; i < 24; ++i) if(!a[i]) return 0;
		if(isFinal()){
			printf("No moves needed\n");
		}else{
			for(int maxd = 1; ; maxd++)
				if(dfs(0, maxd)) break;
		}
		printf("%d\n", a[6]);
	}
	return 0;
}