ch-0503

內容來源《算法競賽進階指南》
date of submission:20191121
tags:歸排
description modelling:
你必定玩過八數碼遊戲,它其實是在一個3*3的網格中進行的,1個空格和1~8這8個數字剛好不重不漏地分佈在這3*3的網格中。
例如:
5 2 8
1 3 _
4 6 7
在遊戲過程當中,能夠把空格與其上、下、左、右四個方向之一的數字交換(若是存在)。
例如在上例中,空格可與左、上、下面的數字交換,分別變成:
5 2 8       5 2 _      5 2 8
1 _ 3       1 3 8      1 3 7
4 6 7       4 6 7      4 6 _
奇數碼遊戲是它的一個擴展,在一個n*n的網格中進行,其中n爲奇數,1個空格和1~n*n-1這n*n-1個數剛好不重不漏地分佈在n*n的網格中。
空格移動的規則與八數碼遊戲相同,實際上,八數碼就是一個n=3的奇數碼遊戲。
如今給定兩個奇數碼遊戲的局面,請判斷是否存在一種移動空格的方式,使得其中一個局面能夠變化到另外一個局面。
輸入格式
多組數據,對於每組數據:
第1行一個整數n,n<500,n爲奇數。
接下來n行每行n個整數,表示第一個局面。
接下來n行每行n個整數,表示第二個局面。
局面中每一個整數都是0~n*n-1之一,其中用0表明空格,其他數值與奇數碼遊戲中的意義相同,保證這些整數的分佈不重不漏。
輸出格式
對於每組數據,若兩個局面可達,輸出TAK,不然輸出NIE。
major steps to solve it:
n數碼問題標準解法:
將n*n的矩陣依次寫成一行(空格除外)
n爲奇數(本題n都是奇數):只要兩個矩陣排成一行後逆序數奇偶性相等便可
n爲偶數:'逆序對數之差'和'兩個局面下空格所在行數之差'奇偶性相等
warnings:
AC code:
#include<cstdio>
using namespace std;
typedef long long ll;
ll a[500005];
ll tmp[500005];
ll num = 0;
void merge(ll left, ll mid, ll right)
{
    ll i = left, j = mid + 1, n = left;
    while (i <= mid && j <= right)
    {
        if (a[i] > a[j])
        {
            tmp[n++] = a[j++];
            num += (j - n);
        }
        else
        {
            tmp[n++] = a[i++];
        }
    }
    if (i > mid)
    {
        while (j <= right)
            tmp[n++] = a[j++];
    }
    else
    {
        while (i <= mid)
            tmp[n++] = a[i++];
    }
    for (ll k = left; k <= right; k++)
    {
        a[k] = tmp[k];
    }
}
void mergesort(ll left, ll right)
{
    if (left < right)
    {
        ll mid = (left + right) / 2;
        mergesort(left, mid);
        mergesort(mid + 1, right);
        merge(left, mid, right);
    }
}
int main()
{
    //freopen("input.txt","r",stdin);
    ll n;
    while(~scanf("%lld",&n)&&n)
    {
        ll id=0;
        for(ll i=0;i<n*n;i++)
        {
            ll x;
            scanf("%lld",&x);
            if(x)    a[id++]=x;
        }
        num=0;
        mergesort(0, id-1);
        ll ans1=num;
        id=0;
        for(ll i=0;i<n*n;i++)
        {
            ll x;
            scanf("%lld",&x);
            if(x)    a[id++]=x;
        }
        num=0;
        mergesort(0, id-1);
        ll ans2=num;
        //cout<<ans1<<' '<<ans2<<endl;
        if(ans1%2==ans2%2)    printf("TAK\n");
        else printf("NIE\n");
    }
    return 0;
}

算法

本站公眾號
   歡迎關注本站公眾號,獲取更多信息