吴昊品游戏核心算法 Round 7(特刊)—— 猜数字系列(数字锁问题) 第三弹(模拟)(HDOJ 1195)

 如图所示,这是一个保险箱,木有错,我们现在假设该密码有四位数,我们也知道密码的存在,我们可以基于以下的规则对这个四位数进行一系列变换,比如:

  (1)可以将这个四位数的某一位上移或者下移,其中,9再往上移动便是0,而0再往下移动即是9。

  (2)两个相邻的数位是可以交换(change)的,但是,有如下规则,最左边的数位不能和最右边的数位发生交换,也就是说,这两个数位,不认为是相邻的。

  我们基于(1)和(2)这两个规则,要找出打开锁(也就是找到密码)需要移动的最少的次数——这里的AI,我们采用宽度优先搜索来实现(BFS+STL,可以看到,这已经是重复多遍的老战术了!对于搜索来说,这种策略确实是相当普遍的)。

  问题来自HDOJ 1195,我以这个问题作为猜数字系列的完结篇。

  

  1  /*
  2      Highlights:
  3     (1)用mark[11][11][11][11]存储四位数,可以方便对其进行调控
  4     (2)在BFS的过程中,对于四位数的每一位,每次朝着三个可能的方向对其进行搜索,并适时标记可能的点
  5     (3)初始的时候,需要判断一下是否一开始就满足条件
  6    */
  7  
  8  #include<iostream>
  9  #include< string>
 10  #include<queue>
 11   using  namespace std;
 12  
 13   struct node
 14  {
 15     char digit[ 5]; // 数组尽量开大一点
 16      int step; // 记录次数       
 17   };
 18  
 19   int mark[ 11][ 11][ 11][ 11];
 20   char a[ 5],b[ 5];
 21  
 22   void bfs()
 23  {
 24     int i;
 25    node cur,q;
 26    queue<node> Queue;
 27    strcpy(q.digit,a); // 将数字锁的初始值装载到q中
 28     q.step= 0; // 初始步骤为0
 29     Queue.push(q);
 30    memset(mark, 0, sizeof(mark)); // 将mark置0,从0开始搜索
 31      while(!Queue.empty())
 32    {
 33      cur=Queue.front(); // 现在的结点
 34       Queue.pop();
 35      mark[cur.digit[ 0]- ' 0 '][cur.digit[ 1]- ' 0 '][cur.digit[ 2]- ' 0 '][cur.digit[ 3]- ' 0 ']= 1;
 36       // 四个位数
 37        for(i= 0;i< 4;i++)
 38      {
 39         // 加一尝试
 40         strcpy(q.digit,cur.digit);
 41        q.step=cur.step+ 1;
 42        q.digit[i]=cur.digit[i]+ 1;
 43         if(q.digit[i]= ' 9 '+ 1)
 44        {
 45          q.digit[i]= ' 1 ';                    
 46        }
 47         // '0'表示还没有被visit的点,'1'表示已经标记过的点                
 48          if (mark[q.digit[ 0] -  ' 0 '][q.digit[ 1] -  ' 0 '][q.digit[ 2] -  ' 0 '][q.digit[ 3] -  ' 0 '] ==  0)
 49        {
 50           if (strcmp(q.digit, b) ==  0)
 51          {
 52            printf( " %d/n ", q.step);
 53             return;
 54          }
 55           else
 56          {
 57            mark[q.digit[ 0] -  ' 0 '][q.digit[ 1] -  ' 0 '][q.digit[ 2] -  ' 0 '][q.digit[ 3] -  ' 0 '] =  1;
 58            Queue.push(q); // 进入队列
 59           }    
 60      }                     
 61       // 减一尝试
 62       strcpy(q.digit, cur.digit);
 63      q.step = cur.step +  1;
 64      q.digit[i] = cur.digit[i] -  1;
 65       if (q.digit[i] ==  ' 0 ')
 66      {
 67        q.digit[i] =  ' 9 ';
 68      }
 69       if (mark[q.digit[ 0] -  ' 0 '][q.digit[ 1] -  ' 0 '][q.digit[ 2] -  ' 0 '][q.digit[ 3] -  ' 0 '] ==  0)
 70      {
 71         if (strcmp(q.digit, b) ==  0)
 72        {
 73          printf( " %d/n ", q.step);
 74           return;
 75        }
 76         else
 77        {
 78          mark[q.digit[ 0] -  ' 0 '][q.digit[ 1] -  ' 0 '][q.digit[ 2] -  ' 0 '][q.digit[ 3] -  ' 0 '] =  1;
 79          Queue.push(q);
 80         }
 81      }
 82       // 交换尝试,由于不需要考虑首尾变换,故i<3就可以的
 83        if (i <  3)
 84      {
 85        strcpy(q.digit, cur.digit);
 86         char temp = q.digit[i]; // 类似于两个数交换,这里有交换数组中相邻元素的值
 87         q.digit[i] = q.digit[i +  1];
 88        q.digit[i +  1] = temp;
 89        q.step = cur.step +  1;
 90         if (mark[q.digit[ 0] -  ' 0 '][q.digit[ 1] -  ' 0 '][q.digit[ 2] -  ' 0 '][q.digit[ 3] -  ' 0 '] ==  0)
 91        {
 92           if (strcmp(q.digit, b) ==  0)
 93          {
 94            printf( " %d/n ", q.step);
 95             return;
 96          }
 97           else
 98          {
 99            mark[q.digit[ 0] -  ' 0 '][q.digit[ 1] -  ' 0 '][q.digit[ 2] -  ' 0 '][q.digit[ 3] -  ' 0 '] =  1;
100            Queue.push(q);
101          }
102        }
103      }
104    }       
105  }
106  
107   void main()
108  {
109     int n;
110    scanf( " %d ",&n); // 读取样例的个数
111      while(n--)
112    {
113      scanf( " %s%s ",a,b);
114       // 运气好,刚好相等!
115        if(strcmp(a,b)== 0)
116        printf( " 0\n ");
117       else
118        bfs();          
119    }    
120  }
121 

你可能感兴趣的:(吴昊品游戏核心算法 Round 7(特刊)—— 猜数字系列(数字锁问题) 第三弹(模拟)(HDOJ 1195))