【八数码扩展】 奇数码问题
传送门
题意
八数码: 在一个$3\times $3的网格中给出\(1\sim 8\)的数字和一个空格,
5 2 8
1 3 _
4 6 7
空格可以和上下左右的数字进行交换,给定一个初始局面和终止局面,判断能否由初始局面转移到终止局面
奇数码为八数码的扩展,即\(n\times n\)阵,给定一个初始局面,一个最终局面,判断能否从初始局面到达最终局面。
数据范围
\(1\leq n < 500\)
题解
对于\(n\times m\) 的数码问题,将除了空格外的数字一次展成一行,初始局面序列为\(a_{i}\),最终局面序列为\(b_{i}\),结论如下:
-
若\(m\)为奇数
-
若\(a_{i}\)的逆序对数\(a\)的奇偶性与\(b_{i}\)的逆序对数\(b\)的奇偶性相同(不考虑\(0\)的逆序对),那么两个局面能够到达
-
即\((a\& 1)==(b\& 1)\)
-
-
如果\(m\)为偶数
-
\(a\)为初始序列的逆序对个数,\(b\)为终止,设\(c\)为两个序列中空格所在的行位置之差的绝对值
-
当\(c\)为奇数,\(a\),\(b\)奇偶性不同,则两个局面可以互相到达
-
当\(c\)为偶数的时候,\(a\),\(b\)奇偶性相同,两个局面可以互相到达,即\((a\& 1)==(b\& 1)^(c\& 1)\)
-
Code
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fi first
#define se second
#define ll long long
#define pb push_back
#define close ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef pair<long long,long long> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef double db;
const ll mod=1e9+7;
const int N=510;
ll powmod(ll a,ll b,ll p)
{
ll res=1;
a%=p;
while(b)
{
if(b&1) res=res*a%p;
a=a*a%p;
b>>=1;
}
return res;
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
int _;
int n;
int a[N*N];
int b[N*N];
int ans[N*N];
int merge_sort(int a[],int l,int r)
{
if(r-l<1)
return 0;
int mid=(l+r)>>1;
int res=0;
res+=merge_sort(a,l,mid);
res+=merge_sort(a,mid+1,r);
int k = 0,i = l,j = mid+1;
while(i <= mid && j <= r)
{
if(a[i] <= a[j])
ans[k++]=a[i++];
else
{
ans[k++]=a[j++];
res+=mid-i+1;
}
}
while(i <= mid)
ans[k++] = a[i++];
while(j <= r)
ans[k++] = a[j++];
for(int i = l,j = 0; i <= r; i++,j++)
a[i]=ans[j];
return res;
}
void solve()
{
while(cin>>n)
{
int ok=0,x;
for(int i = 1;i <= n*n;i++)
{
cin>>x;
if(x==0)
ok=1;
else
a[i-ok] = x;
}
ok=0;
for(int i = 1;i <= n*n;i++)
{
cin>>x;
if(x==0)
ok=1;
else
b[i-ok] = x;
}
memset(ans,0,sizeof ans);
int num1 = merge_sort(a, 1, n*n-1);
memset(ans,0,sizeof ans);
int num2 = merge_sort(b, 1, n*n-1);
if((num1&1 ) == (num2&1) )
cout<<"TAK"<<endl;
else
cout<<"NIE"<<endl;
}
}
int main(){
close;
solve();
}