八数码(广搜)



#include<iostream>
 #include<queue>//用队列解决广搜的问题
 #include <map>//解决队列中两个问题 1.count是否重复 2.用较小的内存存储较大的数组

using namespace std ;

queue<int>q1 ;
 map<int,int>step ;//用较小的内存存储较大的数组

int num = 0  ;
 int dr[4] = {0 , 1 , 0 , -1} ;//左、下、右、上
int dc[4] = {-1 , 0 , 1 , 0} ;
 int bfs() ;//广搜
 int canmoveto(int u , int dire) ;//是否可以移动 
 int moveto(int u , int dire) ;//移动后的状态
 int main()
 {
  int  m , i , num1 ;

 for(i = 1 ; i <= 9 ; i++)//读入数据
     {
      
      cin >> m ;
      num = num * 10 + m ;
     
     }
 
  q1.push(num) ;//入队
  step[num] = 0 ;//初状态步数为0
  num1 = bfs() ;//输出广搜的结果
 
 }
 int bfs()
 {
    int  u , v , i;
  while(!q1.empty())//队列非空 格式
  {

  u = q1.front() ;//访问队首元素
   q1.pop() ;//出队
   for(i = 0 ; i < 4 ; i++)
    {
      if(canmoveto(u,i))//判断是否可以移动
       {
        v = moveto(u , i);//移动后的状态

        if(v == 123456780)//判断是否符合要求
        {
         return (step[u] + 1) ;//返回步数
        }
        if (step.count(v) == 0)//是否重复 这是map的作用
        {
         q1.push(v) ;//新状态入队
         step[v] = step[u] + 1 ;//步数+1
        }
       }
    }
   }
    return -1 ;//没有解返回-1
 }
 int canmoveto(int u , int dire)
 {
  int i , j , row , col , r , c , b[3][3]  ;
  for(i = 2 ; i >= 0 ; i--)//将数字变为二维数组进行移动操作
  {
   for(j = 2 ; j >= 0 ; j--)
   {
      b[i][j] = u % 10 ;
      u /= 10 ;
      if(b[i][j] == 0)
      {
       row = i ;
       col = j ;
   }
  }
  }
     r = row + dr[dire] ;
  c = col + dc[dire] ;
  if(r >= 0 && r < 3 && j >= 0 && j < 3)//判断是否可以移动
  {
   return 1 ;
  }
  else
  {
   return 0 ;
  }
 }
 int moveto(int u , int dire)
 {
  int i , j , row , col , r , c , m , b[3][3] , v = 0 ;
  for(i = 2 ; i >= 0 ; i--)//将数字变为二维数组进行移动操作
  {
   for(j = 2 ; j >= 0 ; j--)
   {
      b[i][j] = u % 10 ;
      u /= 10 ;
      if(b[i][j] == 0)//找到空格并记录
      {
       row = i ;
       col = j ;
   }
  }
  }
   r = row + dr[dire] ;
   c = col + dc[dire] ;
   b[row][col] = b[r][c] ;//空格转换达到新状态
   b[r][c] = 0 ;
   for(i = 0 ; i <= 2 ; 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、付费专栏及课程。

余额充值