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

题目传送门

这个问题是来源于lydrainbowcat老师书上讲排序的一个扩展。当时讲的是奇数码问题,其实这种问题有两种问法:一种局面能否到另一种局面、到达目标局面的最小步数

本文部分内容引用于lydrainbowcat《算法竞赛进阶指南》。

一、判定问题是否有解

我们可以由简至难看这样几个问题:

1.

描述
  你一定玩过八数码游戏,它实际上是在一个3*3的网格中进行的,1个空格和1~8这8个数字恰好不重不漏地分布在这3*3的网格中。
  例如:
  5 2 8
  1 3 _
  4 6 7
  在游戏过程中,可以把空格与其上、下、左、右四个方向之一的数字交换(如果存在)。
  例如在上例中,空格可与左、上、下面的数字交换,分别变成:
  5 2 8 5 2 _ 5 2 8
  1 _ 3 1 3 8 1 3 7
  4 6 7 4 6 7 4 6 _
   
  奇数码游戏是它的一个扩展,在一个n*n的网格中进行,其中n为奇数,1个空格和1~n*n-1这n*n-1个数恰好不重不漏地分布在n*n的网格中。
  空格移动的规则与八数码游戏相同,实际上,八数码就是一个n=3的奇数码游戏。
   
  现在给定两个奇数码游戏的局面,请判断是否存在一种移动空格的方式,使得其中一个局面可以变化到另一个局面。

 奇数码问题两个问题可达,当且仅当他们网格中的数写成不含空格的序列后,两个序列的逆序对数的奇偶性相同。

(证明就不证了qwq)

2.

诸如此题,n*n的网格,只不过n是偶数。

这时候两局面可达当且仅当两序列的(逆序对数+两局面空格间行数差)的奇偶性相同

3.

扩展到n*m?

实际上对于是否有解关键的判定方法取决于列数。

当m为偶数 参考偶数码问题 求解

当n为偶数  参考奇数码问题 求解

本题就可以轻松愉悦地求解了==。

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 int n,m,pos,x,ans,zero;
 8 int seq[1000090],tmp[1000090];
 9 
10 void msort(int l,int r)
11 {
12     if(l==r) return ;
13     int mid=(l+r)>>1;
14     msort(l,mid);
15     msort(mid+1,r);
16     int i=l,j=mid+1,k=l-1;
17     while(i<=mid&&j<=r)
18     {
19         if(seq[i]<=seq[j])
20             tmp[++k]=seq[i],i++;
21         else tmp[++k]=seq[j],j++,ans+=mid-i+1;
22     }
23     while(i<=mid)
24         tmp[++k]=seq[i],i++;
25     while(j<=r)
26         tmp[++k]=seq[j],j++;
27     for(int qwq=l;qwq<=r;qwq++)
28         seq[qwq]=tmp[qwq];
29 }
30 
31 int main()
32 {
33     while(scanf("%d%d",&n,&m)!=EOF&&n!=0)
34     {
35         if(n==0) break;
36         for(int i=1;i<=n;i++)
37             for(int j=1;j<=m;j++)
38             {
39                 scanf("%d",&x);
40                 if(x) seq[++pos]=x;
41                 else zero=n-i;
42             }
43         msort(1,pos);    
44         if(m&1)
45             zero=0;
46         if((ans+zero)%2==0)
47             printf("YES
");
48         else printf("NO
"); 
49         ans=0;pos=0;zero=0;
50     }
51     return 0;
52 }
View Code

开始在主程序中调用msort(1,pos)时出锅了,写成了(1,n),这zz错误也是让我无话可说....。

二、求解最小步数

这类问题一般采用bfs解决,好像还有A*哈希的方法,可是我太菜了不会.....

例题1 Luogu P1379 八数码难题

例题2 Luogu P2730魔板【USACO Trianing】

这个其实是一种变体了qwq。

原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9673434.html