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。

  • 相关阅读:
    ACE_TASK学习
    tomcat:8005端口启动失败的解决办法
    centos7下安装jdk8
    解决github下载慢的一种方法
    page
    数据库
    做jar
    mvc:annotation-driven
    web.xml
    jsp九大内置对象el11内置对象
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9673434.html
Copyright © 2011-2022 走看看