题意:有个#字型的棋盘,2行2列,一共24个格。
如图:每个格子是1或2或3,一共8个1,8个2,8个3.
有A~H一共8种合法操作,比如A代表把A这一列向上移动一个,最上面的格会补到最下面。
求:使中心8个格子数字一致的最少步骤,要输出具体的操作步骤及最终中心区域的数字。如果有多个解,输出字典序最小的操作步骤。
分析 : 还是状态空间的搜索,对象就是一个数字序列,判断中心位置是否一样,可以看出如果使用BFS,每一层还是爆炸,所以使用IDA*,关键还是模拟操作和h函数,这里的h函数是这样定义的,可以看出每一次操作,最多给当前局面添加一个符合要求的数字,那就统计一下中心区域最多的相同数字有多少,然后如果8-h > max_depth - cur_depth的话代表最好的情况下都无法解决,剪枝。模拟操作应该就是很白痴的数组转移赋值了,代码很长,很烦,建议看看刘汝佳的代码。

#include<bits/stdc++.h>
using namespace std;
int Init[25];
int ans_num;
char ans[1000];
bool Is_ok(int *arr)
{
int temp = arr[7];
if(temp!=arr[8] || temp!=arr[9] || temp!=arr[12] || temp!=arr[13] || temp!=arr[16] || temp!=arr[17] || temp!=arr[18])
return false;
return true;
}
inline int h(const int *now)
{
int cnt[4];
memset(cnt, 0, sizeof(cnt));
cnt[now[7]]++, cnt[now[8]]++, cnt[now[9]]++,
cnt[now[12]]++, cnt[now[13]]++, cnt[now[16]]++,
cnt[now[17]]++, cnt[now[18]]++;
int ret = max(cnt[1], cnt[2]);
ret = max(ret, cnt[3]);
return ret;
}
inline void Change(int *tmp, int one, int two, int three, int four, int five, int six, int seven)
{
int index[9];
index[1] = one, index[2] = two, index[3] = three,
index[4] = four, index[5] = five, index[6] = six;
index[7] = seven;
int temp = tmp[one];//!
for(int i=1; i<7; i++)
tmp[index[i]] = tmp[index[i+1]];
tmp[index[7]] = temp;
}
bool DFS(int *now, int cur_depth, int max_depth, int per_dir)
{
if(8 - h(now) > max_depth - cur_depth) return false;
if(cur_depth >= max_depth) return false;//!?
for(int dir=1; dir<=8; dir++){//!
int tmp[25];
if(per_dir!=0){
if((per_dir==1&&dir==6) || (dir==1&&per_dir==6)) continue;
else if((per_dir==2&&dir==5) || (dir==2&&per_dir==5)) continue;
else if((per_dir==3&&dir==8) || (dir==3&&per_dir==8)) continue;
else if((per_dir==4&&dir==7) || (dir==4&&per_dir==7)) continue;
}
for(int i=1; i<25; i++) tmp[i] = now[i];
int top = cur_depth;
switch(dir){
case 1: ans[top]='A';Change(tmp,1,3,7,12,16,21,23);break;
case 2: ans[top]='B';Change(tmp,2,4,9,13,18,22,24);break;
case 3: ans[top]='C';Change(tmp,11,10,9,8,7,6,5);break;
case 4: ans[top]='D';Change(tmp,20,19,18,17,16,15,14);break;
case 5: ans[top]='E';Change(tmp,24,22,18,13,9,4,2);break;
case 6: ans[top]='F';Change(tmp,23,21,16,12,7,3,1);break;
case 7: ans[top]='G';Change(tmp,14,15,16,17,18,19,20);break;
case 8: ans[top]='H';Change(tmp,5,6,7,8,9,10,11);break;
}
if(Is_ok(tmp)){
ans[top+1] = '