• 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 }
  • 相关阅读:
    Linux ifconfig 命令
    linux sed命令就是这么简单
    让博客园博客自动生成章节目录索引
    linux中cat、more、less命令区别详解
    Linux yum源搭建及配置
    关于java中位运算的左移、右移、无符号右移
    一个老话题,short s=s+1的日常
    C语言移位运算符
    关于异或的一些东西和应用
    指针就算指向了常量也不能修改这个常量
  • 原文地址:https://www.cnblogs.com/Kiraa/p/5343538.html
Copyright © 2020-2023  润新知