zoukankan      html  css  js  c++  java
  • 奇数码问题

    奇数码问题

    有一个(n imes n)的网格图,网格由(0sim n-1)组成,现在你可以进行操作,每次操作选择0与其相邻的位置上的数交换位置,给出两个网格图的初始局面,询问这两个局面是否能够互相到达,(nin ext{奇数},1leq nleq 500)

    此题套结论即可,但是不清楚结论,可以参考我的八数码的总结,但是我至今没有它的完整的证明,网上有一篇,但是我看不懂。

    因为n是奇数,于是能够互相到达,当且仅当网格图拆行成列后形成的序列的不考虑0的逆序对个数奇偶性相同,注意这个结论(n=1)时候不成立,需要特判。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define ll long long
    using namespace std;
    ll lxd(int,int,int[]);
    int a[250050],b[250050],at,bt,
    	te[250050];
    int main(){
    	int n;
    	while(scanf("%d",&n)!=EOF){
    		at^=at,bt^=bt;
    		for(int i(1),j,k;i<=n;++i)
    			for(j=1;j<=n;++j){
    				scanf("%d",&k);
    				if(k)a[++at]=k;
    			}
    		for(int i(1),j,k;i<=n;++i)
    			for(j=1;j<=n;++j){
    				scanf("%d",&k);
    				if(k)b[++bt]=k;
    			}
    		if(n==1){puts(a[1]==b[1]?"TAK":"NIE");continue;}
    		puts((lxd(1,at,a)&1)==(lxd(1,bt,b)&1)?"TAK":"NIE");
    	}
    	return 0;
    }
    ll lxd(int l,int r,int a[]){
    	if(l==r)return 0;
    	int mid(l+r>>1),i(l),j(mid+1),k(l);
    	ll ans(lxd(l,mid,a)+lxd(j,r,a));
    	while(i<=mid&&j<=r)
    		if(a[i]<=a[j])te[k++]=a[i++];
    		else te[k++]=a[j++],ans+=mid-i+1;
    	while(i<=mid)te[k++]=a[i++];
    	while(j<=r)te[k++]=a[j++];
    	for(i=l;i<=r;++i)a[i]=te[i];
    	return ans;
    }
    
    
  • 相关阅读:
    耶鲁大学——斯金纳理论基础
    耶鲁大学——弗洛伊德(基础)
    for input 'WID' 报错
    选中当前行wid
    微信支付
    vue.js列表渲染项目实例
    批量删除
    DIV 局部刷新
    DIV块刷新
    CMD DOS命令
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11214075.html
Copyright © 2011-2022 走看看