poj 2286 IDA*搜索
/* 题意:给出一个井字的图案,上面有且只有8个1,8个2,8个3,可以从A~H8个方向拉某行/列,问最少拉多少次使得 中间的8个方格的数字相同 题解:IDA_STAR 关键在实现的方法,通过用一个position的二维数组分别记录4条的对应位置,8个方向搜索,由于每一个点都要记录 当时的情况 注意:往某个方向拉了一格之后,下一层搜索就不应该包含此次的相反方向,避免来回重复搜索; */ #include <cstdio> #include <cstring> #include <algorithm> int position[4][7]= {0,2,6,11,15,20,22, 1,3,8,12,17,21,23, 10,9,8,7,6,5,4, 19,18,17,16,15,14,13}; // 分别按照4条方格记录位置 int mark[24]; // 记录图的值 int midpos[8] = {6,7,8,11,12,15,16,17}; // 中间框的位置 int re[8] = {5,4,7,6,1,0,3,2}; // 8个方向对应的反方向 int ans,ansdepth; char ansstr[10005]; // 最终的字符串 int lstdepth; // IDA_STAR算法时的搜索的深度(不严谨的说法) int minnum(int *pmark) // 估价函数,求最少还差多少个数可以满足条件 { int sum1,sum2,sum3; sum1 = sum2 = sum3 = 0; for(int i=0; i<8; i++) { if (1 == pmark[midpos[i]]) sum1++; else if (2 == pmark[midpos[i]]) sum2++; else if (3 == pmark[midpos[i]]) sum3++; } int ret = sum1; if (ret < sum2) ret = sum2; if (ret < sum3) ret = sum3; return 8 - ret; } int dfs(int depth, int *pmark, int predir) { int mint = minnum(pmark); if (depth + mint > lstdepth) // 搜索到lstdepth时回溯 { return depth + mint; } if (mint == 0) { ans = pmark[6]; ansdepth = depth; return depth; } int mindepth = 1 << 30; // 每一次都求出后面的结点中最小的估价 for(int i=0; i<8; i++) { if (predir == i) continue; int tmpmark[24]; for(int j=0; j<24; j++) tmpmark[j] = pmark[j]; if (i < 4) { int t = tmpmark[position[i][0]]; for(int j=1; j<7; j++) tmpmark[position[i][j-1]] = tmpmark[position[i][j]]; tmpmark[position[i][6]] = t; } else { int c; if (4 == i) c = 1; else if (5 == i) c = 0; else if (6 == i) c = 3; else if (7 == i) c = 2; int t = tmpmark[position[c][6]]; for(int j=5; j>=0; j--) tmpmark[position[c][j+1]] = tmpmark[position[c][j]]; tmpmark[position[c][0]] = t; } ansstr[depth] = i+'A'; int nextdepth = dfs(depth+1, tmpmark, re[i]); mindepth = std::min(nextdepth, mindepth); if (ans) return 0; } return mindepth; } int main(void) { while (~scanf("%d",&mark[0]) && mark[0]) { for(int i=1; i<24; i++) scanf("%d",&mark[i]); ans = ansdepth = 0; lstdepth = minnum(mark); ansstr[0] = 0; while (ans == 0 && lstdepth <= 100) { lstdepth = dfs(0,mark,-1); } if (ansdepth == 0) printf("No moves needed"); else { for(int i=0; i<ansdepth; i++) printf("%c",ansstr[i]); } printf("\n%d\n",ans); } return 0; }