The Rotation Game POJ-2286(迭代加深搜索)
题意:对一个#字行图案的格子上填上1,2,3数字,可以进行A-H八种变化,使邻近#字中心空格的8个数字都相同,求字典序最小的方案。
分析:首先该题需要剪枝,不然会超时,可以将估价函数设为中心最少还有几个数字不相同(h(x)<=h*(x)),然后就是状态的表示,可以直接采用题目所给的数字序列,然后操作时建立一个操作的映射表进行操作(本来想建立一个链表表示#字,看来下别人的确实发现没必要)。
#include <cstdio> #include <iostream> #include <cstring> using namespace std; int rot[10][10]={ //操作打表 {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 {23,21,17,12,8,3,1}, //E {22,20,15,11,6,2,0}, //F {13,14,15,16,17,18,19}, //G {4,5,6,7,8,9,10} //H }; int cent[10]={6,7,8,11,12,15,16,17}; //中间8个位置 int a[30],maxh; char put[100001]; bool check() { for(int i=1;i<8;i++) if(a[cent[i]]!=a[cent[0]]) return false; return true; } int dis() { int cnt=0,mi=100010; for(int i=1;i<=3;i++) { cnt=0; for(int j=0;j<8;j++) { if(a[cent[j]]!=i) cnt++; } mi=min(mi,cnt); } return mi; } void mov(int x) { int t=a[rot[x][0]]; for(int i=0;i<6;i++) a[rot[x][i]]=a[rot[x][i+1]]; a[rot[x][6]]=t; } int dfs(int h) { if(h>maxh) return 0; if(check()){put[h]='\0'; return 1;} if(h+dis()>maxh) return 0; for(int i=0;i<8;i++) { put[h]='A'+i; mov(i); if(dfs(h+1)) return 1; if(i%2) mov((i+3)%8); else mov((i+5)%8); } return 0; } int main() { while(scanf("%d",a)&&a[0]) { for(int i=1;i<24;i++) scanf("%d",a+i); maxh=1; if(check()) cout<<"No moves needed"<<'\n'<<a[cent[0]]<<endl; else{ while(!dfs(0)) maxh++; printf("%s\n%d\n",put,a[cent[0]]);} } }

浙公网安备 33010602011771号