现在的位置: 首页 > 综合 > 正文

POJ 2286 The Rotation Game 搜索-IDA*+迭代加深 POJ 2286 The Rotation Game 搜索-IDA*+迭代加深

2017年12月17日 ⁄ 综合 ⁄ 共 2702字 ⁄ 字号 评论关闭

POJ 2286 The Rotation Game 搜索-IDA*+迭代加深

分类:
搜索

132人阅读
评论(0)
收藏
举报

题目地址:http://poj.org/problem?id=2286

本题若用广搜,空间需求量非常大,空间不足。深搜的话,深度很难控制,容易陷入死循环。在这个时候就要用到迭代加深的深搜方法。

所谓迭代加深,就是在深度无上限的情况下,先预估一个深度(尽量小)进行搜索,如果没有找到解,再逐步放大深度搜索。这种方法虽然会导致重复的遍历 某些结点,但是由于搜索的复杂度是呈指数级别增加的,所以对于下一层搜索,前面的工作可以忽略不计,因而不会导致时间上的亏空。

这种方法,可以算作是DFS和BFS的结合。适合大树而可行解不是很深的题目。

IDA*对于最优解层数小,每次扩展状态多的时候是一个杀手锏啊。IDA*就是一个加了层数限制depth的DFS,超过了限制就不在搜索下去,如果在当前层数没有搜到目标状态,就加大层数限制depth,这里还只是一个IDA算法,并不是A*的。当然我们可以用A*的估计函数去剪枝,如果当前深度d+h()>depth的时候就可以不再搜索下去了,这样就是IDA*了。

  对于这道题,我们把状态用一维数组存储,然后对每个元素设定相应的编号:

            0     1
            2     3
      4  5  6  7  8  9  10
            11    12
      13 14 15 16 17 18 19
            20    21
            22    23

  并且把每个操作的相应编号用数组存起来就好处理了:

AC代码:

  1. #include <iostream>   
  2. #include <cstdio>   
  3. #include <cstdlib>   
  4. #include <cmath>   
  5. #include <cstring>   
  6. #include <string>   
  7. #include <vector>   
  8. #include <list>   
  9. #include <deque>   
  10. #include <queue>   
  11. #include <iterator>   
  12. #include <stack>   
  13. #include <map>   
  14. #include <set>   
  15. #include <algorithm>   
  16. #include <cctype>   
  17. using namespace std;  
  18.   
  19. typedef long long LL;  
  20. const int N=2222222;  
  21. const LL II=1000000007;  
  22.   
  23. int n,m,depth;  
  24. int vis[2222222],s[24];  
  25. int path[N];  
  26. int t[4][2]={-1,0,0,1,1,0,0,-1};  
  27. char op[]="ABCDEFGH";  
  28. int mid[8]={6,7,8,11,12,15,16,17};//中间位置
      
  29. int fan[8]={5,4,7,6,1,0,3,2};//反方向移动,回归
      
  30. int xh[8][7]=//8种操作,每次移动7位
      
  31. {  
  32.     0,2,6,11,15,20,22,  
  33.     1,3,8,12,17,21,23,  
  34.     10,9,8,7,6,5,4,  
  35.     19,18,17,16,15,14,13,  
  36.     23,21,17,12,8,3,1,  
  37.     22,20,15,11,6,2,0,  
  38.     13,14,15,16,17,18,19,  
  39.     4,5,6,7,8,9,10  
  40. };  
  41.   
  42. int max3(int a,int b,int c)  
  43. {  
  44.     return (a>b?a:b)>c?(a>b?a:b):c;  
  45. }  
  46.   
  47. int get(int a[])  
  48. {  
  49.     int i,cnt[4]={0,0,0,0};  
  50.     for(i=0;i<8;i++)  
  51.         cnt[s[mid[i]]]++;  
  52.     return 8-max3(cnt[1],cnt[2],cnt[3]);// 8-返回中间最多的那个数 的数量
      
  53. }  
  54.   
  55. void move(int k)  
  56. {  
  57.     int i,t=s[xh[k][0]];  
  58.     for(i=1;i<7;i++)  
  59.         s[xh[k][i-1]]=s[xh[k][i]];  
  60.     s[xh[k][6]]=t;  
  61. }  
  62.   
  63. bool dfs(int k)  
  64. {  
  65.     if(k>=depth)  
  66.         return false;  
  67.     int i,h;  
  68.     for(i=0;i<8;i++)  
  69.     {  
  70.         move(i);  
  71.         path[k]=i;  
  72.         h=get(s);  
  73.         if(h==0)  
  74.             return true;  
  75.         if((k+h)<depth&&dfs(k+1))//当前的步数加还需要的最少步数<depth
      
  76.             return true;  
  77.         move(fan[i]);//移回来   
  78.     }  
  79.     return false;  
  80. }  
  81.   
  82. int main()  
  83. {  
  84.     int i,j;  
  85.     while(scanf("%d",&s[0])&&s[0])  
  86.     {  
  87.         for(i=1;i<24;i++)  
  88.             scanf("%d",&s[i]);  
  89.         depth=get(s);//差最少的步数   
  90.         if(depth==0)  
  91.         {  
  92.             printf("No moves needed\n%d\n",s[mid[0]]);  
  93.             continue;  
  94.         }  
  95.         while(!dfs(0))  
  96.             depth++;//如果不行,最少步数+1   
  97.         for(i=0;i<depth;i++)  
  98.             printf("%c",op[path[i]]);  
  99.         printf("\n%d\n",s[6]);//输出中间位置的数字
      
  100.     }  
  101.     return 0;  
  102. }  

抱歉!评论已关闭.