UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]

解题思路:

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

    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\n",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\n");
 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\n%d\n",u[tar[0]]);
107             continue;
108         }
109         for(maxd=1;;maxd++)
110             if(solve())
111                 break;
112         printf("%s\n%d\n",P1,num);
113         //time_;
114     }
115     return 0;
116 }
时间: 2024-10-25 14:39:18

UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]的相关文章

uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索

迭代加深搜索 自己看的时候第一遍更本就看不懂..是很水,但智商捉急也是没有办法的事情. 好在有几个同学已经是做过了这道题并且对迭代加深搜索的思路有了一定的了解,所以在某些不理解的地方询问了一下他们的见解, 真的是很有帮助,也许自己想要想很久才能想明白,还会很痛苦,稍微问一下别人的想法,点上一个方向,剩下的自己就能想得明白了. 迭代加深. 把answer(需要的步数或其他)在主函数里面从零往上递加,此之谓 "层数",亦可谓之"深度".用书上的话就是: 从小到大枚举深度

UVa 1343 The Rotation Game(IDA*)

主要是设计乐观估计函数来减枝 假设中心区域有6个2,2个3,那肯定是消掉3最好,毕竟就两个. 那么理想情况下,旋转一次就能把一个3变成2,那么最少操作2次. 我们用h()来计算最少还要操作几次,其原理是假设中心区域都放1或2或3,返回至少操作的次数中最小的数 maxd是假设最多能操作的数; d是已经操作的数; 那么就可以得出乐观估计函数   h()+d>maxd 其含义为 : 若  至少还要操作次数  加上  已经操作的次数  大于  最多总共操作的次数就退出 . 其次就是节点的处理了,编个号数

UVA 11212 Editing a Book [迭代加深搜索IDA*]

11212 Editing a Book You have n equal-length paragraphs numbered 1 to n. Now you want to arrange them in the order of 1, 2, . . . , n. With the help of a clipboard, you can easily do this: Ctrl-X (cut) and Ctrl-V (paste) several times. You cannot cut

Power Calculus UVA - 1374 迭代加深搜索

迭代加深搜索经典题目,好久不做迭代加深搜索题目,拿来复习了,我们直接对当前深度进行搜索,注意剪枝,还有数组要适当开大,因为2^maxd可能很大 题目:题目链接 AC代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <cstring> 7 #incl

hdu 1560 DNA sequence(迭代加深搜索)

DNA sequence Time Limit : 15000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 15   Accepted Submission(s) : 7 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description The twenty-first century

【迭代加深搜索】埃及分数问题

谢谢阿苏~http://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5856756 [迭代加深搜索(ID,iterative deepening)]:从小到大枚举上限maxd,每次执行只考虑深度不超过maxd的结点. ------对于可以用回溯法求解但解答树的深度没有明显上限的题目,可以考虑ID算法: ------优点:它主要是在递归搜索函数的开头判断当前搜索的深度是否大于预定义的最大搜索深度,如果大于,就退出这一层的搜索,如果不大于,就

hdu 1560 迭代加深搜索

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560 只能说bin神太给力了.. 又学到不少新知识.. 迭代加深搜索,貌似 又叫IDA*, 就是给搜索深度一个限制,搜索到一个满足条件就结束. 注意剪枝~ 代码: #include <iostream> #include <cstdio> #include <cstring> using namespace std; char g[10][10]; int size[10];

“埃及分数”问题浅谈对迭代加深搜索的理解

迭代加深搜索(IDDFS)的思想 迭代加深搜索一般用来求解状态树"非常深",甚至深度可能趋于无穷,但是"目标状态浅"的问题.如果用普通的DFS去求解,往往效率不够高.此时我们可以对DFS进行一些改进.最直观的一种办法是增加一个搜索的最大深度限制maxd,一般是从1开始.每次搜索都要在maxd深度之内进行,如果没有找到解,就继续增大maxd,直到成功找到解,然后break. 如下图所示,如果用DFS,需要15步才能找到结点3,但是用迭代加深搜索,很快即可找到结点3.

IDDFS(迭代加深搜索)精选题and总结

引入:什么是IDDFS? 在计算机科学中,迭代深化搜索(iterative deepening search)或者更确切地说迭代深化深度优先搜索 (iterative deepening depth-first search (IDS or IDDFS)) 是一个状态空间(状态图)搜索策略.在这个搜索策略中,一个具有深度限制的深度优先搜索算法会不断重复地运行,并且同时放宽对于搜索深度的限制,直到找到目标状态.IDDFS 与广度优先算法是等价的,但对内存的使用会少很多:在每一步迭代中,它会按深度优