六数码 广搜例题 附带一些实用的小用法



六数码这道题本身是一道广搜的例题 主要部分是广搜模版 大多数人已重复多遍 应该已经掌握 所以我在此说一下小细节 反正模版我是会的 小细节我真的不会

看大佬的博客学会了这些细节 在这里把精华详细地说出来 b数在心 大佬勿笑 如有不对 还望指正

但是这些小细节只能一点一点积累了

1.队列的清空 操作如下

while(!q1.empty())

{

 q1.pop(); // 队首元素一直出队直到队列为空达到清空队列的作用

}

2.used的清空  used数组是定义在map这个头文件上面的

used.clear

3.具体怎么输出的问题

我发现这个题目提交的时候有个bug 我用了本来写好的程序提交是对的 然后改了一点提交也是对的 这就比较纠结了  我又看了一遍题目 发现我犯了一个比较扯淡的错误

我觉得这个问题应该不只我一个人犯吧 只有我当时脑子短路我也是比较无奈的

输出方法1 : 输入一个测例 输出一个测例的结果 如此运行下去 这么提交是对的 但是不符合题意  题意应该是一口气输出多个测例的结果 这个问题应该比较常见 应避免

效果大概是这样的 (在这里我只列举两个测例):

第一步 : 输入 1 3 2 4 5 6

第二步 : 回车 这时候就输出 No 了 (明显不符合题意)

第三步 :再输入 1 3 2 4 5 6

第四步 : 回车 这时候还输出 No

第五步 : 按ctrl+z

第六步 : 回车 程序结束

输出方法2 : 在我思考人生之后觉得这么理解应该是比较正确的 用一个数组存一下每个测例得出的结果 最后再一口气输出全部测例的结果

改正后的效果

第一步 : 输入 1 3 2 4 5 6

第二步 : 回车 这时候不会输出

第三步 :再输入 1 3 2 4 5 6

第四步 : 回车 这时候还不会输出

第五步 : 按ctrl+z

第六步 : 回车 输出结果程序结束 (这时候我就觉得效果比较符合题意了 如果我的理解有问题 还望指正 共同进步)


题目和代码如下



现有一两行三列的表格如下:

A B C
D E F

把1、2、3、4、5、6六个数字分别填入A、B、C、D、E、F格子中,每个格子一个数字且各不相同。每种不同的填法称为一种布局。如下:

1 3 5
2 4 6
布局1

2 5 6
4 3 1
布局2

定义α变换如下:把A格中的数字放入B格,把B格中的数字放入E格,把E格中的数字放入D格,把D格中的数字放入A格。
定义β变换如下:把B格中的数字放入C格,把C格中的数字放入F格,把F格中的数字放入E格,把E格中的数字放入B格。

问:对于给定的布局,可否通过有限次的α变换和β变换变成下面的目标布局:

1 2 3
4 5 6
目标布局


输入:

本题有多个测例,每行一个,以EOF为输入结束标志。每个测例的输入是1到6这六个数字的一个排列,空格隔开,表示初始布局ABCDEF格中依次填入的数字。


输出:

每个输出占一行。可以转换的,打印Yes;不可以转换的,打印No。


输入样例:

1 3 5 2 4 6 2 5 6 4 3 1


输出样例:

No Yes

#include<iostream>
 #include<stdio.h>
 #include<math.h>
 #include<queue>//队列解决广搜问题
#include<map>//使用map是为了方便标记
 #include<stdlib.h>
 using namespace std ;
 queue<int>q1 ;
 map<int , int> used ;//判断是否遍历过
int bfs() ; //广搜找答案
int moveto(int u , int dire) ;
 void print(int n) ;
  //1 3 5 2 4 6
 //2 5 6 4 3 1
 int main()
 {
     int num = 0 , i , m , n  , a[100] , counter = 0 ;
     while(scanf("%d",&m)!=EOF)//以EOF为结束标志 
    {  
         num = m ;
        
         for(i = 0 ; i < 5 ; i++)
         {
             scanf("%d" , &m);
             num = num * 10 + m ;
         }//将输入的布局直接转为6位数

      while(!q1.empty()) // 队首一直出队直到队列为空             
        {
            q1.pop();
        }
        used.clear();//多组数据 需要清空used 
       
       
         q1.push(num);//将起点加入队列
         used[num]=1;
         a[counter] = bfs() ;//输出搜索的结果
         counter ++ ;
        }
       for(i = 0 ; i < counter ; i++)
       {
   
         if(a[i]==0) printf("No\n");//输出结果
         if(a[i]==1) printf("Yes\n");
      
    }
  return 0;
 }


int bfs()//广搜找答案 这个子函数是广搜的模版 已练习多遍
 {
  int i , u , v ;
  while(!q1.empty())
  {
   u = q1.front() ;
   q1.pop() ;
   for(i = 1 ; i <= 2 ; i++)
   {
    v = moveto (u , i) ;
    if(v == 123456)
    {
     return 1 ;//找的到解 return 1 
    }
    if(used.count(v) == 0)
    {
     q1.push(v) ;
     used[v] = 1 ;
    }
   }
  }
  return 0 ;//找不到解 return 0
 }
 int moveto(int u , int dire)
 {
 /*定义α 把A b[0][0] B b[0][1],把B b[0][1]  E b[1][1],把E b[1][1] D b[1][0],把D b[1][0]  A b[0][0]。
 定义β   把B b[0][1] C b[0][2],把C b[0][2]  F b[1][2],把F b[1][2] E b[1][1],把E b[1][1] B b[0][1]
 */
  int i , j , b[2][3] , v = 0 , temp1 , temp2 , temp3 , temp4 ;
  if(dire == 1) // a转换
  {
    for(i = 1 ; i >= 0 ; i--)
    {
     for(j = 2 ; j >= 0 ; j--)
     {
       b[i][j] = u % 10 ;
     u /= 10 ;
     }
    }
       temp1 = b[0][0] ;//设置多个临时变量方便转换
       temp2 = b[0][1] ;
       temp3 = b[1][1] ;
       temp4 = b[1][0] ;
       b[0][1] = temp1 ;
       b[1][1] = temp2 ;
       b[1][0] = temp3 ;
       b[0][0] = temp4 ;
      
    for(i = 0 ; i <= 1 ; i++)
    {
     for(j = 0 ; j <= 2 ; j++)
     {
      v = v * 10 + b[i][j] ;
     }
    }
    return v ;
  }
  //把B b[0][1] C b[0][2],把C b[0][2]  F b[1][2],把F b[1][2] E b[1][1],把E b[1][1] B b[0][1]
  else  // b转换 方法和a相同
  {
      for(i = 1 ; i >= 0 ; i--)
      {
       for(j = 2 ; j >= 0 ; j--)
       {
        b[i][j] = u % 10 ;
        u /= 10 ;
       }
      }
         temp1 = b[0][1] ;
         temp2 = b[0][2] ;
         temp3 = b[1][2] ;
         temp4 = b[1][1] ;
         b[0][2] = temp1 ;
         b[1][2] = temp2 ;
         b[1][1] = temp3 ;
         b[0][1] = temp4 ;
   for(i = 0 ; i <= 1 ; i++)
    {
      for(j = 0 ; j <= 2 ; j++)
      {
      v = v * 10 + b[i][j] ;
      }
    }
      return v ;
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值