控制奇数数行的样式只能用n吗_奇数码问题--->M×N Puzzle

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

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

//#include

#include

#include

#include

#include

#include

using namespace std;

inline int read(){

int x=0,o=1;char ch=getchar();

while(ch!='-'&&(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;

}

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

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

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

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

//#include

#include

#include

#include

#include

#include

using namespace std;

inline int read(){

int x=0,o=1;char ch=getchar();

while(ch!='-'&&(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;

}

标签:ch,Puzzle,个数,奇偶性,问题,数码,include,逆序

来源: https://www.cnblogs.com/PPXppx/p/11253917.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值