解题思路:
这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是:
1)状态转移代价很大,一次需要向八个方向寻找;
2)哈希表更新频繁;
3)采用广度优先搜索结点数越来越多,耗时过大;
经过简单计算,最长大概10次左右的变换就能出解,于是笔者就尝试采用IDA*,迭代加深搜索的好处是:
1)无需存储状态,节约时间和空间;
2)深度优先搜索查找的结点数少;
3)递归方便剪枝;
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <ctime> 6 7 using namespace std; 8 9 #define time_ printf("time :%f ",double(clock())/CLOCKS_PER_SEC) 10 #define maxs 735471 11 typedef int state[24]; 12 int init_p[24]; 13 state start; 14 int num; 15 int seq[maxs]; 16 int cur; 17 char P1[maxs]; 18 int maxd; 19 inline void get_P(char *P){ 20 for(int i=0;i<cur;i++) 21 P[i]=seq[i]+'A'; 22 } 23 int pos[8][7]={ 24 {0,2,6,11,15,20,22}, 25 {1,3,8,12,17,21,23}, 26 {10,9,8,7,6,5,4}, 27 {19,18,17,16,15,14,13}, 28 {23,21,17,12,8,3,1}, 29 {22,20,15,11,6,2,0}, 30 {13,14,15,16,17,18,19}, 31 {4,5,6,7,8,9,10} 32 }; 33 int tar[8]={6,7,8,11,12,15,16,17}; 34 35 inline int tar_num(const state &p){ 36 int cnt=0; 37 for(int k=1;k<=3;k++){ 38 int c=0; 39 for(int i=0;i<8;i++) 40 if(p[tar[i]]==k) 41 c++; 42 cnt=max(c,cnt); 43 } 44 return cnt; 45 } 46 inline void move(state& s,int i){ 47 int temp=s[pos[i][0]]; 48 int j=0; 49 for(;j<6;j++) 50 s[pos[i][j]]=s[pos[i][j+1]]; 51 s[pos[i][j]]=temp; 52 } 53 bool dfs(state& u,int s_d){ 54 if(s_d==maxd){ 55 if(tar_num(u)==8){ 56 num=u[tar[0]]; 57 return true; 58 } 59 return false; 60 } 61 if(8-tar_num(u)>maxd-s_d) 62 return false; 63 for(int i=0;i<8;i++){ 64 move(u,i); 65 seq[cur++]=i; 66 if(dfs(u,s_d+1)) 67 return true; 68 cur--; 69 if(i%2) move(u,(i+3)%8); 70 else move(u,(i+5)%8); 71 } 72 return false; 73 } 74 inline void init(){ 75 memset(seq, -1, sizeof seq); 76 cur=0; 77 } 78 bool solve(){ 79 init(); 80 bool ok=false; 81 state u; 82 memcpy(u, init_p, sizeof u); 83 if(tar_num(u)==8){ 84 printf("‘No moves needed "); 85 } 86 if(dfs(u,0)){ 87 ok=true; 88 get_P(P1); 89 } 90 return ok; 91 } 92 int main() { 93 94 while(1){ 95 memset(P1, 0, sizeof P1); 96 for(int i=0;i<24;i++){ 97 scanf("%d",&init_p[i]); 98 if(init_p[i]==0) { 99 //time_; 100 return 0; 101 } 102 } 103 state u; 104 memcpy(u, init_p, sizeof u); 105 if(tar_num(u)==8){ 106 printf("No moves needed %d ",u[tar[0]]); 107 continue; 108 } 109 for(maxd=1;;maxd++) 110 if(solve()) 111 break; 112 printf("%s %d ",P1,num); 113 //time_; 114 } 115 return 0; 116 }