zoukankan      html  css  js  c++  java
  • 奇数码问题--->M×N Puzzle

    AcWing

    奇数码游戏是八数码问题的一个扩展,在一个n×n的网格中进行,其中n为奇数,1个空格和1~(n^2-1)(n^2-1)个数恰好不重不漏地分布在n×n的网格中.空格移动的规则与八数码游戏相同,实际上,八数码就是一个n=3的奇数码游戏.现在给定两个奇数码游戏的局面,请判断是否存在一种移动空格的方式,使得其中一个局面可以变化到另一个局面。

    分析:奇数码游戏两个局面可达,当且仅当两个局面下网格中的数依次写成1行(n*n-1)个元素的序列后(不考虑空格,也就是0),逆序对个数的奇偶性相同.证明请自行参考网上资料.所以我们只要求两次逆序对的个数,然后判断奇偶性是否相同就行了.

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=250005;
    int ans1,ans2,a[N],b[N],c[N];
    inline void msort1(int l,int r){
        if(l==r)return;
        int mid=(l+r)/2;
        msort1(l,mid);msort1(mid+1,r);
        int i=l,j=mid+1,k=l;
        while(i<=mid&&j<=r){
            if(a[i]<=a[j]){b[k]=a[i];k++;i++;}
            else{
                b[k]=a[j];k++;j++;
                ans1+=mid-i+1;
            }
        }
        while(i<=mid){b[k]=a[i];k++;i++;}
        while(j<=r){b[k]=a[j];k++;j++;}
        for(int i=l;i<=r;++i)a[i]=b[i];
    }
    inline void msort2(int l,int r){
        if(l==r)return;
        int mid=(l+r)/2;
        msort2(l,mid);msort2(mid+1,r);
        int i=l,j=mid+1,k=l;
        while(i<=mid&&j<=r){
            if(c[i]<=c[j]){b[k]=c[i];k++;i++;}
            else{
                b[k]=c[j];k++;j++;
                ans2+=mid-i+1;
            }
        }
        while(i<=mid){b[k]=c[i];k++;i++;}
        while(j<=r){b[k]=c[j];k++;j++;}
        for(int i=l;i<=r;++i)c[i]=b[i];
    }
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		int tot1=0,tot2=0;
    		for(int i=1;i<=n*n;++i){
    			int x=read();
    			if(x)a[++tot1]=x;
    		}
    		for(int i=1;i<=n*n;++i){
    			int x=read();
    			if(x)c[++tot2]=x;
    		}
    		if(n==1){puts("TAK");continue;}
    		ans1=0;ans2=0;
    		msort1(1,tot1);msort2(1,tot2);
    		if(((ans1&1)&&(ans2&1))||(!(ans1&1)&&!(ans2&1)))puts("TAK");
    		else puts("NIE");
    	}
        return 0;
    }
    

    POJ

    本题是奇数码问题的拓展,网格变成(n*m),奇偶性不确定,且其中一个局面的逆序对个数为0.

    我们只要求一个局面的逆序对个数,然后根据列数奇偶性分情况讨论:

    1.若列数m为奇数,同上题,逆序对个数奇偶性相同即可,而其中一个局面已知逆序对个数为0,也就是偶数了.

    2。若列数m为偶数,这次一个局面“逆序对个数+两个局面下空格之间的行数之差”与另一个局面的逆序对个数奇偶性相同即可.其中已知那个逆序对个数为0的局面的空格0在第n行.

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=1000005;
    int ans,a[N],b[N];
    inline void msort(int l,int r){
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	msort(l,mid);msort(mid+1,r);
    	int i=l,j=mid+1,k=l;
    	while(i<=mid&&j<=r){
    		if(a[i]<=a[j])b[k++]=a[i++];
    		else{
    			b[k++]=a[j++];
    			ans+=mid-i+1;
    		}
    	}
    	while(i<=mid)b[k++]=a[i++];
    	while(j<=r)b[k++]=a[j++];
    	for(int i=l;i<=r;++i)a[i]=b[i];
    }
    int main(){
    	while(1){
    		int n=read(),m=read();if(!n&&!m)break;
    		int tot=0,pos;
    		for(int i=1;i<=n;++i)
    			for(int j=1;j<=m;++j){
    				int x=read();
    				if(x)a[++tot]=x;
    				else pos=i;
    			}
    		ans=0;msort(1,tot);
    		if(m&1){
    			if(ans&1)puts("NO");
    			else puts("YES");
    		}
    		else{
    			if((ans+n-pos)&1)puts("NO");
    			else puts("YES");
    		}
    	}
        return 0;
    }
    
    
  • 相关阅读:
    win10前面板耳机没声音
    学计算机的值得一看的文章,跟帖也很有水平啊
    ubuntu下编译caffe
    pip卡住不动的解决方案
    数字图像处理处理中的数学怎么提高?
    安装vmall5:从ebak恢复数据,需要配置php.ini
    python入门(7)Python程序的风格
    python入门(6)输入和输出
    python入门(5)使用文件编辑器编写代码并保存执行
    python入门(4)第一个python程序
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11253917.html
Copyright © 2011-2022 走看看