UVA 1343

解题思路:

  这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是:

    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 }
原文地址:https://www.cnblogs.com/Kiraa/p/5343538.html