题意: 题意就是八数码,给了一个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. HDU1043 Eight(八数码:逆向BFS打表+康托展开)题解

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  2. poj 1077-Eight(八数码+逆向bfs打表)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

  3. 【双向广搜+逆序数优化】【HDU1043】【八数码】

    HDU上的八数码 数据强的一B 首先:双向广搜 先处理正向搜索,再处理反向搜索,直至中途相遇 visit 和 队列都是独立的. 可以用一个过程来完成这2个操作,减少代码量.(一般还要个深度数组) 优化 ...

  4. Eight(经典题,八数码)

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  5. HDOJ-1043 Eight(八数码问题+双向bfs+高效记录路径+康拓展开)

    bfs搜索加记录路径 HDOJ-1043 主要思路就是使用双向广度优先搜索,找最短路径.然后记录路径,找到结果是打印出来. 使用康拓序列来来实现状态的映射. 打印路径推荐使用vector最后需要使用a ...

  6. hdu1043Eight (经典的八数码)(康托展开+BFS)

    建议先学会用康托展开:http://blog.csdn.net/u010372095/article/details/9904497 Problem Description The 15-puzzle ...

  7. HDU 1043 Eight 【经典八数码输出路径/BFS/A*/康托展开】

    本题有写法好几个写法,但主要思路是BFS: No.1 采用双向宽搜,分别从起始态和结束态进行宽搜,暴力判重.如果只进行单向会超时. No.2 采用hash进行判重,宽搜采用单向就可以AC. No.3 ...

  8. 【洛谷】P1379 八数码难题(bfs)

    题目 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局 ...

  9. hdu 1043 Eight (八数码问题)【BFS】+【康拓展开】

    <题目链接> 题目大意:给出一个3×3的矩阵(包含1-8数字和一个字母x),经过一些移动格子上的数后得到连续的1-8,最后一格是x,要求最小移动步数. 解题分析:本题用BFS来寻找路径,为 ...

随机推荐

  1. 细说MySQL连接查询:内连、左连和右连

    转: 细说MySQL连接查询:内连.左连和右连 简介: MySQL 的连接查询,通常都是将来自两个或多个表的行结合起来,基于这些表之间的共同字段,进行数据的拼接.首先,要确定一个主表作为结果集,然后将 ...

  2. HDOJ-6666(简单题+模拟题)

    quailty and ccpc hdoj-6666 题目很简单,按照题目的意思模拟就行了,排序. #include<iostream> #include<cstdio> #i ...

  3. 翻译:《实用的Python编程》03_06_Design_discussion

    目录 | 上一节 (3.5 主模块) | 下一节 (4 类) 3.6 设计讨论 本节,我们重新考虑之前所做的设计决策. 文件名与可迭代对象 考虑以下两个返回相同输出的程序. # Provide a f ...

  4. Git 常用命令 和 安装

    这年头不会点git还真不能与别人进行代码交流 安装 windowns版下载:https://git-scm.com/download/win ,下载完成后就自己手动安装 ,很简单就不多说. Ubunt ...

  5. gpfdist原理解析

    gpfdist原理解析 前言:gpfdist作为批量向postgresql写入数据的工具,了解其内部原理有助于正确使用以及提供更合适的数据同步方案.文章先简要介绍gpfdist的整体流程,然后针对重要 ...

  6. python学习之类的装饰器进阶版

    装饰器可以修饰函数,同样,也可以修饰类 装饰器 def deco(func):    print('======>被修饰的')return func 装饰器装饰函数的方式,语法糖 @decode ...

  7. Codeforces 784B Santa Claus and Keyboard Check

    题面: 传送门 B. Santa Claus and Keyboard Check Input file: standard input Output file: standard output Time ...

  8. 使用shell脚本替换Hadoop配置文件的值

    因为懒汉式的实现是线程安全的,所以会降低整个访问速度,而且每次访问都要判断一次.有没有更好的方式实现呢?可以使用"双重检查枷锁"的方式来实现. 所谓"双重检查加锁&quo ...

  9. 史上超强拷贝仓——GitHub 热点速览 v.21.11

    作者:HelloGitHub-小鱼干 Clone-Wars 是真的强,能细数 70+ 知名应用网站的源码,即便你不看代码,也可以了解下各大网站的所用技术栈.同样很强的是用 OpenCV 实现的图片转 ...

  10. Java并发编程之基础理论

    内存模型   主内存.工作内存与Java堆.栈.方法区并不是同一个层次的内存划分 勉强对应起来 从定义来看,主内存对应Java堆中对象实例数据部分,工作内存对应虚拟机栈中部分区域 从更低层次来说,主内 ...