zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    HDU 5486 Difference of Clustering 图论
    HDU 5481 Desiderium 动态规划
    hdu 5480 Conturbatio 线段树 单点更新,区间查询最小值
    HDU 5478 Can you find it 随机化 数学
    HDU 5477 A Sweet Journey 水题
    HDU 5476 Explore Track of Point 数学平几
    HDU 5475 An easy problem 线段树
    ZOJ 3829 Known Notation 贪心
    ZOJ 3827 Information Entropy 水题
    zoj 3823 Excavator Contest 构造
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9673434.html
Copyright © 2011-2022 走看看