The Eight Puzzle, among other sliding-tile puzzles, is one of the famous problems in artificial intelligence. Along with chess, tic-tac-toe and backgammon, it has been used to study search algorithms.

The Eight Puzzle can be generalized into an M × N Puzzle where at least one of M and N is odd. The puzzle is constructed with MN − 1 sliding tiles with each a number from 1 to MN − 1 on it packed into a M by N frame with one tile missing. For example, with M = 4 and N = 3, a puzzle may look like:

1 6 2
4 0 3
7 5 9
10 8 11

Let's call missing tile 0. The only legal operation is to exchange 0 and the tile with which it shares an edge. The goal of the puzzle is to find a sequence of legal operations that makes it look like:

1 2 3
4 5 6
7 8 9
10 11 0

The following steps solve the puzzle given above.

START

1 6 2
4 0 3
7 5 9
10 8 11

DOWN

1 0 2
4 6 3
7 5 9
10 8 11
LEFT
1 2 0
4 6 3
7 5 9
10 8 11

UP

1 2 3
4 6 0
7 5 9
10 8 11

 

RIGHT

1 2 3
4 0 6
7 5 9
10 8 11

UP

1 2 3
4 5 6
7 0 9
10 8 11
UP
1 2 3
4 5 6
7 8 9
10 0 11

LEFT

1 2 3
4 5 6
7 8 9
10 11 0

GOAL

Given an M × N puzzle, you are to determine whether it can be solved.

Input

The input consists of multiple test cases. Each test case starts with a line containing M and N (2 ≤ M, N ≤ 999). This line is followed by M lines containing N numbers each describing an M × N puzzle.

The input ends with a pair of zeroes which should not be processed.

Output

Output one line for each test case containing a single word YES if the puzzle can be solved and NO otherwise.

Sample Input

3 3
1 0 3
4 2 5
7 8 6
4 3
1 2 5
4 6 9
11 8 10
3 7 0
0 0

Sample Output

YES
NO 题意:给你一个m*n的矩阵,0代表空,0位置可以和上下左右位置交换,问是否可以变成1~m*n-1顺序排列且0在第m*n的位置的图,看上面例子。
思路:这就是一个奇数码问题的扩展,我们将其看成一条链,将0去除。
①对于n的奇数码问题,我们知道若能从一个图转换成另一张图,只需要比较两个图的逆序对奇偶性是否相同即可。(上下交换,交换n-1个数,n-1为偶数,不影响逆序对奇偶性)
②对于n的偶数码问题,我们左右交换依然不增减逆序对,但是上下交换,将交换n-1个数,n-1为奇数,将改变逆序对奇偶性,我们需要判断 【一个图的逆序对+空位置行的差值】与【另一图的逆序对】
 #include<cstdio>
#include<iostream> using namespace std; const int maxn = 1e6+;
int a[maxn];
typedef long long ll;
int Mergesort(int l,int r)
{
int mid = (l+r)/;
int b[r-l+];
int i=l,j=mid+;
int m=;
int cnt = ;
while(i <= mid && j <= r)
{
if(a[i] > a[j])
b[m++] = a[j++],cnt += mid-i+;
else
b[m++] = a[i++];
}
while(i <= mid)
{
b[m++] = a[i++];
}
while(j <= r)
{
b[m++] = a[j++];
}
m = ;
for(int i=l; i<=r; i++)
{
a[i] = b[m++];
}
return cnt;
} void Merge(int l,int r,ll& ans)
{
if(l >= r)
return;
int mid = (l+r)/;
Merge(l,mid,ans);
Merge(mid+,r,ans);
ans += Mergesort(l,r);
}
int n,m;
int main()
{
while(~scanf("%d%d",&n,&m)&&n&&m)
{
int tmp;
int cnt = ;
int row;
for(int i=; i<=n; i++)
{
for(int j=; j<=m; j++)
{
scanf("%d",&tmp);
if(tmp)
a[cnt++] = tmp;
else row = i;
}
}
ll ans = ;
Merge(,cnt-,ans);
int flag = ;
if(m&){if((ans & ) == )flag = ;}
else if((ans+n-row) % == )flag = ;
if(flag)printf("YES\n");
else printf("NO\n");
}
}
												

M × N Puzzle POJ - 2893(奇数码)的更多相关文章

  1. CH Round #72 奇数码问题[逆序对 观察]

    描述 你一定玩过八数码游戏,它实际上是在一个3*3的网格中进行的,1个空格和1~8这8个数字恰好不重不漏地分布在这3*3的网格中. 例如:5 2 81 3 _4 6 7 在游戏过程中,可以把空格与其上 ...

  2. poj2893 M*N puzzle 【n*m数码问题小结】By cellur925

    题目传送门 这个问题是来源于lydrainbowcat老师书上讲排序的一个扩展.当时讲的是奇数码问题,其实这种问题有两种问法:一种局面能否到另一种局面.到达目标局面的最小步数. 本文部分内容引用于ly ...

  3. AcWing:108. 奇数码问题(归并排序 + 逆序数)

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

  4. 区间dp E - Multiplication Puzzle POJ - 1651

    E - Multiplication Puzzle  POJ - 1651 这个题目没有特别简单,但是也没有我想象之中的那么难,这个题目时区间dp,因为我们是要对区间进行考虑的. 但是呢,这个也和动态 ...

  5. POJ 2893 M × N Puzzle——八数码有解条件

    题意:给定M*N的数码图,问能否移动到最终状态 分析 有解的判定条件可见 八数码有解条件 值得一提的是,这道题求逆序对卡树状数组,只能用归并排序. #include<cstdio> #in ...

  6. POJ 2893 M × N Puzzle(树状数组求逆序对)

                                                               M × N Puzzle Time Limit: 4000MS   Memory ...

  7. POJ 2893 M × N Puzzle

    逆序对 n 数码问题的扩展 对于一个n * m 的问题来说,结论和 列数 m 奇偶有关 对于 m 是奇数来说 , 两个局面互相可达,当且仅当这两个局面按顺序写成一个数列,这个数列的逆序对数的奇偶性相同 ...

  8. HDU 3600 Simple Puzzle 归并排序 N*N数码问题

    先介绍八数码问题: 我们首先从经典的八数码问题入手,即对于八数码问题的任意一个排列是否有解?有解的条件是什么? 我在网上搜了半天,找到一个十分简洁的结论.八数码问题原始状态如下: 1 2 3 4 5 ...

  9. 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 ...

随机推荐

  1. python 知识梳理

    1.数据类型:字符串,列表,元组,字典,集合.处理每种数据类型的函数 2.判断与循环部分 3.高级函数:lambda,map,reduce,filter 4.自定义模块以及第三方模块 5.函数式编程 ...

  2. Confluence 6 缓存状态

    Confluence 为系统的内部缓存提供了缓存的状态以便于你对缓存的大小的命中率进行跟踪,在必要的情况下,你可以对缓存进行调整,让缓存能够更好的满足你的使用需求.请查看 Performance Tu ...

  3. Spark-SQL之DataFrame操作

    Spark SQL中的DataFrame类似于一张关系型数据表.在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现.可以参考,Scala提供的DataFra ...

  4. java多线程快速入门(二十)

    1.Java.util的线程安全工具类 Vector(线程安全) ArrayList(线程不安全) HashTable(线程安全) HashMap(线程不安全) 2.将线程不安全集合变为线程安全集合 ...

  5. binlog2sql之MySQL数据闪回实践

    DBA或开发人员,有时会误删或者误更新数据,如果是线上环境并且影响较大,就需要能快速回滚.传统恢复方法是利用备份重搭实例,再应用去除错误sql后的binlog来恢复数据.此法费时费力,甚至需要停机维护 ...

  6. centos6 防火墙iptables操作整理

    使用语句 前言:  iptables的启动文件位置再:  /etc/init.d/iptables , srevice iptables调用的就是这里的执行文件 查看防火墙状态   service i ...

  7. python 内置数据类型之字符串

    1.3 字符串 字符串本身就是一个有序(从左至右)的字符的集合.是序列这种类型的一种,后面还要学习列表与元组. 在这一节中,需要了解字符串的定义,特殊字符,转义与抑制转义:字符串基本操作.格式化等. ...

  8. SqlServer 分页存储过程

    SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[usp_CommonDataResourcePaged ...

  9. 作为完美主义者(强迫症)如何将linux的eth1网卡修改为eth0网卡

    1:由于你是克隆的虚拟机或者直接就是使用别人的Centos操作系统直接打开到自己本地的虚拟机,网卡可能就是eth1而不是eth0,下面简单写一下如何将eth1修改为eth0,步骤如下所示: 2:如果你 ...

  10. Top 查看某些或者某个进程(top -p pid)

    https://blog.csdn.net/zhangfn2011/article/details/7488746?utm_source=blogxgwz5