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;
}