奇数码问题
Posted hhyx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了奇数码问题相关的知识,希望对你有一定的参考价值。
# 题意
奇数码为八数码的扩展,即为n的正方形矩阵,n为奇数,给定一个初始局面,一个最终局面,判断能否从初始局面到达最终局面。
# 题解
1) 两个局面可达当且仅当两个局面中除了空格中的数意外展成一行后(不考虑空格)即n*n - 1个数字,逆序对个数的奇偶性相同
2) 必要性:
空格左右移动的时候,序列不变,空格上下移动的时候,相当于某个数与它前或后边的n-1个数交换了位置,因为n-1是偶数,所以逆序对的变化个数也只能是偶数。
当n为偶数的时候,结论:两个局面可达当且仅当两个局面对应网格展成序列后,(逆序对数之差)和(两个局面下空格所在的行数之差)奇偶性相同。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=510; 5 int a[N*N]; 6 int b[N*N]; 7 int ans[N*N]; 8 int merge_sort(int a[],int l,int r){ 9 if(r-l<1) 10 return 0; 11 12 int mid=(l+r)>>1; 13 14 int res=0; 15 res+=merge_sort(a,l,mid); 16 res+=merge_sort(a,mid+1,r); 17 18 int k = 0,i = l,j = mid+1; 19 while(i <= mid && j <= r){ 20 if(a[i] <= a[j]) 21 ans[k++]=a[i++]; 22 else{ 23 ans[k++]=a[j++]; 24 res+=mid-i+1; 25 } 26 } 27 28 while(i <= mid) 29 ans[k++] = a[i++]; 30 while(j <= r) 31 ans[k++] = a[j++]; 32 33 for(int i = l,j = 0; i <= r; i++,j++) 34 a[i]=ans[j]; 35 return res; 36 } 37 int main(){ 38 ios::sync_with_stdio(0); 39 cin.tie(0); 40 cout.tie(0); 41 42 int n; 43 while(cin>>n) { 44 int ok=0,x; 45 for(int i = 1;i <= n*n;i++) 46 { 47 cin>>x; 48 if(x==0) 49 ok=1; 50 else 51 a[i-ok] = x; 52 } 53 ok=0; 54 for(int i = 1;i <= n*n;i++) 55 { 56 cin>>x; 57 if(x==0) 58 ok=1; 59 else 60 b[i-ok] = x; 61 } 62 memset(ans,0,sizeof ans); 63 int num1 = merge_sort(a, 1, n*n-1); 64 memset(ans,0,sizeof ans); 65 int num2 = merge_sort(b, 1, n*n-1); 66 67 if((num1&1 ) == (num2&1) ) 68 printf("TAK "); 69 else 70 printf("NIE "); 71 } 72 }
以上是关于奇数码问题的主要内容,如果未能解决你的问题,请参考以下文章