题目链接:点击查看

题目大意:给出一个n*m的数码问题,问是否能到达最终状态

题目分析:对于数码问题,我们先一步一步分析,先简单看一下定义:

八数码的问题描述为:
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局,找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

八数码问题算是经典bfs问题了,因为是bfs,所以自然可以求出最小步数以及路径输出,之前我也写过博客介绍了,这里就不过多展开讨论了,我们现在讨论的问题没有那么复杂,只是单纯的讨论某个状态能否通过规则操作到达最终状态,也就是判断当前状态是否有解

首先我们先上升为n*n数码问题,n为奇数:

关于证明我也不太会证明,简单说一下结论吧,就是我们将整个n*n-1个数(不包含空格)依次写成一行的一个序列后,逆序对个数的奇偶性相同,必要性的证明:空格左右移动时,转换成的序列显然不变,上下移动时,相当于某个数与它前面或后面的n-1个数交换了位置,因为n是奇数,所以n-1是偶数,所以逆序对的变化也只能是偶数,而最后目标的状态逆序对的数目为0,所以当前状态的逆序对的数目必须为偶数才能达到目标状态,换句话说,若判断两个状态能否到达的条件就是其逆序对数的奇偶性是否一致

现在我们将问题再上升为n*n,n为偶数的情况:

原理同上,只不过空格在上下移动的时候,会和n-1个数交换了位置,因为此时的n为偶数,所以n-1为奇数,所以此时逆序对的变化只能为奇数,而奇数+奇数等于偶数,奇数+偶数等于奇数,所以当n为奇数的时候,此时判断状态之间的关系还需要看空格上下交换了几次位置,换句话说,若判断两个状态能否到达的条件是“逆序对之差”和“两个局面下空格所在的行数之差”的奇偶性是否一致

最后我们将问题上升为n*m,n和m为任意正整数:

通过上面的分析,我们会发现其实答案只与列数有直接的关系,所以我们已经不用管n了,只需要根据m来讨论就好了:

  1. 若m为奇数,则m-1为偶数,判断可达性即判断逆序对数的奇偶性即可
  2. 若m为偶数,则m-1为奇数,判断可达性即判断逆序对数以及空格所差的行数记得奇偶性即可

结论说完之后,那么对于这个题目,我们只需要先求一下逆序对数,然后根据m来分情况讨论一下就好了,注意一下这个题目卡了时间,只能用归并排序求逆序数,而不能用树状数组或线段树来求

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e6+100;int a[N],b[N];int merge_sort(int l,int r)//归并排序
{if(l==r)return 0;int mid=l+r>>1;int ans=merge_sort(l,mid)+merge_sort(mid+1,r);int p=l,q=mid+1;for(int i=l;i<=r;i++){if(q>r||p<=mid&&a[p]<=a[q])b[i]=a[p++];else{b[i]=a[q++];ans+=mid-p+1;}}for(int i=l;i<=r;i++)a[i]=b[i];return ans;
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int n,m;while(scanf("%d%d",&n,&m)!=EOF&&n+m){int cnt=0,zero;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int num;scanf("%d",&num);if(num)a[++cnt]=num;elsezero=n-i;}int ans=merge_sort(1,cnt);if(m&1)//若m为奇数zero=0; if((ans+zero)&1)//ans和zero奇偶性不同 printf("NO\n");elseprintf("YES\n");}return 0;
}

POJ - 2893 M × N Puzzle(n*m数码问题+逆序对结论)相关推荐

  1. 奇数码问题(逆序对)

    Description 你一定玩过八数码游戏,它实际上是在一个33的网格中进行的,1个空格和1~8这8个数字恰好不重不漏地分布在这33的网格中. 例如: 5 2 8 1 3 _ 4 6 7 在游戏过程 ...

  2. puzzle(1011)平面逆推:康斯逆推

    目录 一,康斯puzzle 二,康斯逆推 三,六边形康斯逆推 一,康斯puzzle 康斯是一家做平面逆推问题的出版商. 官网:点击打开链接 二,康斯逆推 最强大脑的康斯逆推,其实就是数图: 给出每行每 ...

  3. 【POJ - 1651】Multiplication Puzzle(区间dp)

    题干: The multiplication puzzle is played with a row of cards, each containing a single positive integ ...

  4. 成长轨迹59 【ACM算法之路 百炼poj.grids.cn】【递归】【2694:逆波兰表达式】

    http://poj.grids.cn/practice/2694/ [ce代码] 1 #include <stdio.h> 2 #include <math.h> 3 4 d ...

  5. 108. 奇数码问题【思维 / 逆序对】

    n为奇数,左右交换不改变逆序对数个数,上下交换不改变逆序对奇偶性. 结论就是,将其转化成1维,将0去除掉,求逆序对的数量,看这两个的逆序对的奇偶性是否相同即可. #include<bits/st ...

  6. 《算法竞赛进阶指南》刷题记录

    总算闲下来一些辣!然后最近发现其实看书是真真很有效但是一直没有落实!所以决定落实一下这段时间把这本书看完题目做完! 然后发现还有挺多题目挺巧妙的于是一堆博客预警,,,可能最近会写很多比较水(但是我还是 ...

  7. 【HDOJ1043】八数码的八境界

    2019独角兽企业重金招聘Python工程师标准>>> 研究经典问题,空说不好,我们拿出一个实际的题目来演绎.八数码问题在北大在线测评系统中有一个对应的题,题目描述如下: Eight ...

  8. 八数码问题中的逆序数

    转载自:http://blog.csdn.net/ju136/article/details/6876647(选取部分). 对于给定八数码棋局的初始状态,我们的目标是通过交换空格与其相邻棋子使棋盘达到 ...

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

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

最新文章

  1. SQL Server高可用性部署实施 SQL server 群集
  2. jupyter修改密码后无法启动服务器,搭建jupyter远程连接服务器
  3. 微信小程序 封装接口
  4. [补] windows C socket编程——大物实验预约
  5. java map 值排序_使用Java8 Stream API对Map类型按照键或值进行排序
  6. mysql 水平拆分实例_2021先定个小目标?搞清楚MyCat分片的两种拆分方法和分片规则!(二):水平拆分实例解析和代码实现!...
  7. 【Python学习】 caffe-master 之 mnist 详解
  8. MySQL忘记root密码重置密码(5.7版本)
  9. 英文识别 java_Java-百度API的图片文字识别(支持英文)
  10. 关于 IMPP/XMPP/SIMPLE 这几种即时通讯协议和NAT traversal
  11. 唯有读书,能战胜这个爆炸的时代
  12. Echarts制作标签云图
  13. XTDrone--执行roslaunch px4 indoor1.launch 遇到的问题
  14. python pandas.errors.InvalidIndexError: Reindexing only valid with uniquely valued
  15. 耐得住寂寞方能不寂寞
  16. javascript 获取邮箱的后缀
  17. Inverted file index
  18. SRAM、PSRAM、SPI FLASH初步认识
  19. 亚马逊个人创业这条路行的通吗?
  20. vue中父传子,父传孙说明

热门文章

  1. mysql xtrabackup 主从_使用 Xtrabackup 在线对MySQL做主从复制
  2. MySQL高级 - SQL优化 - or优化
  3. Nginx负载均衡策略之轮询与加权轮询
  4. 分库与分表设计-垂直切分
  5. zipkin server 数据持久化问题
  6. IOC 容器初始化小结
  7. 微信支付 - 构建商户订单
  8. 函数式接口的概念函数式接口的定义
  9. arduino编译失败_Arduino编译时失败
  10. Spring Boot 整合 Shiro