题意: 题意就是八数码,给了一个3 * 3 的矩阵,上面有八个数字,有一个位置是空的,每次空的位置可以和他相邻的数字换位置,给你一些起始状态 ,给了一个最终状态,让你输出怎么变换才能达到目的.


思路: 首先我们先判断一下可不可以达到最终目的,方法是根据逆序数,只要终止状态和起始状态的逆序数(空的位置不算)奇偶性相同就能,否则不能;

证明 :

加入当前空的位置是i,针对3 * 3 的也就是八数码问题(可能有别的数码,根据奇偶性答案不同) 如果向前或向后移动的话 当前的逆序数不变,如果像上移动的话有三种情况, 移动过来的这个数比那两个数都大,逆序数 - 2 ,移动过来的这个数比那两个数都小 逆序数 + 2,比一个大,比另一个小,逆序数 + 1 - 1 不变,所以怎么移动逆序数奇偶性不变,所以只有起始状态可终止状态逆序数奇偶性相同才能转换..

解决了判断,剩下的就是输出方法了,直接暴搜会TLE出"翔"来(测试数据太多),我们观察会发现,题目最终的目的地是同一个状态,无论什么最后都要到题目中给的那个终点,那么我们可以直接以终点为起点,遍历一边所有状态,然后把它存起来,等问的时候我们只要把存的方法变换一下就ok了,首先把整个序列颠倒过来,因为我们是反向打表,然后相应的 上 变 下 下 变 上 ... 因为是反向搜索..然后输出来就ok了, 这让我想起了以前做过的一道最短路,一群牛去一个地方开会,在回来问所有路径的最短和,路是单向的,我们只要直接以开会点为起点,跑两边最短路就ok了..想法是一样的.上代码.



//逆向BFS打表 AC

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<map>
#include<queue>

using namespace std;

typedef struct
{
   int now_map[10];
   string root;
   int id0;
}NODE;

map<int ,string>ans_map;
map<int ,int>mk;
NODE xin ,tou;
char ans[800000];
int end_map[10] = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,0};

bool hash(int now[] ,string root)
{
   int sum = 0 ,e = 1;
   for(int i = 1 ;i <= 9 ;i ++)
   {
      sum += e * now[i];
      e *= 10;
   }
   if(mk[sum])
   return 1;
   mk[sum] = 1;
   ans_map[sum] = root;
   return 0;
}

void DB_BFS()
{
   for(int i = 1 ;i <= 9 ;i ++)
   xin.now_map[i] = end_map[i];
   xin.root = "";
   xin.id0 =  9;
   queue<NODE>q;
   q.push(xin);
   ans_map.clear();
   mk.clear();
   hash(xin.now_map ,"ud");
   while(!q.empty())
   {
      tou = q.front();
      q.pop(); 
          
      if(tou.id0 >= 4)
      {
         xin = tou;
         xin.root = tou.root + 'u';
         xin.now_map[xin.id0] = tou.now_map[xin.id0-3];
         xin.now_map[xin.id0-3] = 0;
         xin.id0 -= 3;     
         if(!hash(xin.now_map ,xin.root))
         {           
            q.push(xin);
         }
     }
       
      if(tou.id0 <= 6)
      {
         xin = tou;
         xin.root = tou.root + 'd';
         xin.now_map[xin.id0] = tou.now_map[xin.id0+3];
         xin.now_map[xin.id0+3] = 0;
         xin.id0 += 3;
         if(!hash(xin.now_map ,xin.root))
         {
            q.push(xin);
         }   
      }
      
      if(tou.id0 != 1 && tou.id0 != 4 && tou.id0 != 7)
      {
         xin = tou;
         xin.root = tou.root + 'l';
         xin.now_map[xin.id0] = tou.now_map[xin.id0-1];
         xin.now_map[xin.id0-1] = 0;
         xin.id0 --;
         if(!hash(xin.now_map ,xin.root))
         {
            q.push(xin);                
         }
      }
      
      if(tou.id0 != 3 && tou.id0 != 6 && tou.id0 != 9)
      {
         xin = tou;
         xin.root = tou.root + 'r';
         xin.now_map[xin.id0] = tou.now_map[xin.id0+1];
         xin.now_map[xin.id0+1] = 0;
         xin.id0 ++;    
         if(!hash(xin.now_map ,xin.root))
         {
            q.push(xin);                
         }
      }
   }
}

int main ()
{
   int i ,id0;
   char str[5];
   DB_BFS();
   NODE A;
   while(~scanf("%s" ,str))
   {
      if(str[0] == 'x')
      {
         A.id0 = 1;
         A.now_map[1] = 0;
      }
      else
      A.now_map[1] = str[0] - 48;
      for(i = 2 ;i <= 9 ;i ++)
      {
         scanf("%s" ,str);
         if(str[0] == 'x')
         {
            A.id0 = i;
            A.now_map[i] = 0;
         }
         else
         A.now_map[i] = str[0] - 48;
      }
      
      int sum = 0;
      int ss = 0 ,e = 1;
      for(i = 1 ;i <= 9 ;i ++)
      {
         ss += A.now_map[i] * e;
         e *= 10;
         if(!A.now_map[i])continue;
         for(int j = 1 ;j < i ;j ++)
         if(A.now_map[i] < A.now_map[j])
         sum ++;
      }
      if(sum % 2)
      {
         printf("unsolvable\n");
         continue;
      }
      
      int l = ans_map[ss].length();   
      for(i = 0 ;i < l ;i ++)
      {
         char c = ans_map[ss][l-i-1];
         if(c == 'u')
         ans[i] = 'd';
         if(c == 'd')
         ans[i] = 'u';
         if(c == 'l')
         ans[i] = 'r';
         if(c == 'r')
         ans[i] = 'l';
      }
      ans[l] = '\0';
      puts(ans);
      
   }
   return 0;
}     
   


hdu1043 经典的八数码问题 逆向bfs打表 + 逆序数相关推荐

  1. 移动拼图游戏(八数码问题) BFS版

    小时候玩过的移动拼图游戏.有一个3*3的棋盘,其中有0-8这9个数字,0表示空格,每次移动只能把空格旁边的数字移到空格,即与0相邻的数字可以和0交换位置. 求从初始状态 2 3 0 7 1 6 5 8 ...

  2. 人工智能作业 八数码启发式搜索与bfs比较

    问题描述 3×3九宫棋盘,放置数码为1 -8的8个棋牌,剩下一个空格,只能通过棋牌向空格的移动来改变棋盘的布局. 要求:根据给定初始布局(即初始状态)和目标布局(即目标状态),如何移动棋牌才能从初始布 ...

  3. Poj 1077 eight(BFS+全序列Hash解八数码问题)

    一.题意 经典的八数码问题,有人说不做此题人生不完整,哈哈.给出一个含数字1~8和字母x的3 * 3矩阵,如: 1  2  X            3 4  6            7  5  8 ...

  4. hdu 1043 Eight 经典八数码问题

    hdu 1043 Eight 经典八数码问题 题意描述:给出一个3×3的矩阵(包含1-8数字和一个字母x),经过一些移动格子上的数后得到连续的1-8,最后一格是x,要求最小移动步数. 算法分析:经典的 ...

  5. 【八数码问题】基于状态空间法的知识表示与状态搜索:无信息搜索(BFS/DFS) 启发式搜索(A*)

    前言 一.问题引入 二.状态空间法 1. 知识及其表示 2. 状态空间法定义 3. 问题求解 三.基于状态空间搜索法解决八数码问题 1. 八数码问题的知识表示 2. 状态空间图搜索 1. 无信息搜索 ...

  6. A_Star 康托展开 八数码问题

    A_Star算法是一个主要用bfs实现的寻路算法,当数据量庞大的时候往往有更高的时间效率,可以看成是Dijkstra算法的升级版. "盲目搜索会浪费很多时间和空间, 所以我们在路径搜索时, ...

  7. 八数码 poj 1077 广搜 A* IDA*

    经典的八数码问题,有人说不做此题人生不完整,哈哈. 状态总数是9! = 362880 种,不算太多,可以满足广搜和A*对于空间的需求. 状态可以每次都动态生成,也可以生成一次存储起来,我用的动态生成, ...

  8. 学习笔记--八数码问题

    题目链接 https://www.luogu.org/problemnew/show/P1379 分析 经典的八数码问题,有双向BFS和\(IDA*\)的方法,这里使用的是\(A*\)启发式搜索. 简 ...

  9. 八数码问题可解性及扩展

    对于给定八数码棋局的初始状态,我们的目标是通过交换空格与其相邻棋子使棋盘达到目标状态. 其中,游戏规则是只能交换空格与其上下左右四个方向的相邻棋子. 假设棋局目标状态为如下形式:(A.B.C.D.E. ...

最新文章

  1. Linux设备驱动开发-linux驱动中的非阻塞访问方式
  2. .NET1.1中预编译ASP.NET页面实现原理浅析[1]自动预编译机制浅析
  3. ionic android 版本号,ionic android 版本release 和 签名(示例代码)
  4. Golang——TCP、UDP实现并发(服务端与客户端)
  5. Nginx学习之四-Nginx进程同步方式-自旋锁(spinlock)
  6. 2020年python工资一般多少-2020届毕业生874万,这个岗位月薪2万竟无人问津...
  7. python服务器搭建nginx_从0开始搭建nginx-uWSGI-Django-python服务器
  8. 写java一般用什么系统字体_JavaSE中使用非系统自带的字体
  9. Food Webs - 网络中度及集聚系数实现
  10. [置顶]史上最详细最全的Linux上安装Oracle的教程-centos7-humf
  11. 如何学好高中数学 提高高中数学成绩秒杀技巧(这几点很重要)
  12. 服务器FPM日志出现seems busy (you may need to increase pm.start_servers解决办法
  13. python数据可视化——英雄联盟人物战力分析(条形图)
  14. 论文阅读:HAD-Net: A Hierarchical Adversarial Knowledge Distillation Network for Improved Enhanced Tumour
  15. Ethercat 学习总结一:协议总结
  16. 端午节主题模板--Ideappt原创PPT模板系列
  17. Ansible_SaltStack_BatchShell三款运维软件对比
  18. 酷我音乐盒2014 v7.6.0.0 官方免费版
  19. demo1—java读取Excel文件到数据库、java制作准考证
  20. matlab 限速标志数字识别之去除标志外环噪声

热门文章

  1. Effective stl---笔记
  2. 用户通过WEB方式更改AD域帐户密码
  3. 初步解读Golang中的接口相关编写方法
  4. 使用JS在textarea在光标处插入内容
  5. 解决人际矛盾的英语口语10条
  6. 随手小记 才知道系列
  7. 在ASP.Net2.0中使用UrlRewritingNet实现链接重写(转)
  8. 小心!目录删除及重命名操作 ,一定丢失Session~~!
  9. 黑马lavarel教程---9、缓存操作
  10. Nginx upstream的5种权重分配方式分享