poj2893 M × N Puzzle

交了N发后终于A了。。。

发一波dalao的题解:

某状态的奇偶性定义为逆序对(不包括0的)总数的奇偶性。

此题目终态为偶数

首先,0的左右移动不改变奇偶性。

1.N为奇数,上下移动不改变奇偶性,故逆序数为偶的YES

2.N为偶数,上下移动逆序数变化为±1,此时还要考虑0的竖直距离,逆序数%2 == 距离%2 时YES

 
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1005;
int a[N*N],cnt=0,v[N*N];
int solve_(int l,int r){
    if(l==r)return 0;
    int mid=(l+r)>>1;
    int ret=solve_(l,mid)+solve_(mid+1,r);
    int t1=l,t2=mid+1,cnt=0;
    for(int i=l;i<=r;++i){
        if(t2>r||t1<=mid&&a[t1]<a[t2])v[++cnt]=a[t1],++t1;
        else v[++cnt]=a[t2],++t2,ret+=mid-t1+1;
    }
    for(int i=l;i<=r;++i)a[i]=v[i-l+1];
    return ret;
}
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)){
        if(!n&&!m)break;
        cnt=0;int re=0;
        for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            int t;
            scanf("%d",&t);
            if(t)
            a[++cnt]=t;
            else re=i;
        }
        int ans=solve_(1,cnt);
        re=n-re;
        if(m&1)re=0;
        if(re%2==ans%2)printf("YES");
        else printf("NO");
        puts("");
    }
    return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/Dream-Runner/p/10132460.html