ida*果然比a*强太多了,少了hash判重和堆维护,是估价函数和DFS的完美结合啊!
嗯,主要是DFS函数中第二行的那个强剪枝太给力了!IDA*的灵魂啊!
基本的架构就是如此了,可以任意套。
//poj2286
#include <iostream>
#include <cmath>
using namespace std;
const int b[5][8] = { 7,8,9,12,13,16,17,18,
1,3,7,12,16,21,23,0,
2,4,9,13,18,22,24,0,
11,10,9,8,7,6,5,0,
20,19,18,17,16,15,14,0};
const int c[9] = {0,1,2,3,4,6,5,8,7};
int a[25],stk[1010],bound,x,final;
bool ans;
int h(int *a) {
int tmp[3]={0,0,0};
for (int i=0;i<8;i++)
tmp[a[b[0][i]]-1]++;
return 8-max(max(tmp[0],tmp[1]),tmp[2]);
}
void trans(int *a,int p) {
if (p<=4) {
int tmp = a[b[p][0]];
for (int i=0;i<6;i++)
a[b[p][i]]=a[b[p][i+1]];
a[b[p][6]]=tmp;
} else {
p-=4;
int tmp = a[b[p][6]];
for (int i=6;i>0;i--)
a[b[p][i]]=a[b[p][i-1]];
a[b[p][0]]=tmp;
}
}
int dfs(int *a,int dep,int pre_move) {
int hv = h(a);
if (hv + dep > bound) return hv+dep;
if (hv==0) {
ans = true;
final = a[7];
return dep;
}
int next_bound = 10000;
for (int i=1;i<=8;i++) {
if (abs(c[i]-pre_move)==4) continue; //与上一步相反的移动
int tmp[25];
for (int j=1;j<=24;j++) tmp[j]=a[j];
trans(tmp,c[i]);
stk[dep]=i;
int new_bound = dfs(tmp,dep+1,c[i]);
if (ans) return new_bound;
next_bound = min(next_bound,new_bound);
}
return next_bound;
}
void ida_star() {
memset(stk,0,sizeof(stk));
bound = h(a);
ans = false;
while (!ans && bound<=100)
bound = dfs(a,0,-100);
for (int i=0;i<bound;i++) printf("%c",stk[i]+64);
printf("\n%d\n",final);
}
int main() {
while (~scanf("%d",&x)) {
if (x==0) break;
a[1]=x;
for (int i=2;i<=24;i++)
scanf("%d",&a[i]);
if (h(a)==0) {
printf("No moves needed\n");
printf("%d\n",a[7]);
continue;
}
ida_star();
}
return 0;
}