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

    原题链接:108. 奇数码问题



    解题思路

    奇数码问题两个局面可以达成,当且仅当两个局面下网格中的数以此写成1行 n*n-1 个元素的序列后(不考虑空格),逆序对个数的奇偶性相同。例如题目描述中的第一个局面可以写成[5 2 8 1 3 4 6 7]。该结论的必要性很容易证明:空格左右移动时,写数交换了位置,因为n-1是偶数,所以逆序对数的变化也只能是偶数。

    上面的结论还可以扩展到n为偶数的情况,此时两个局面可达,当且仅当两个局面对应网格写成序列后,“逆序对数之差”和“两个局面下空格所在行数之差”奇偶性相同。事实上,在n*m网格中(n,m>=2)也服从上述的两个结论之一(根据列数奇偶性分情况讨论)。

    总而言之,n*m数码问题的有解性判定,可以转化为归并问题排序就逆序对来解决

    样例代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=510;
    int n,m,a[N*N],b[N*N],c[N*N],i,j,k;
    long long cnt;
    void merge(int a[],int l,int r)
    {
        if (r-l<1)
            return ;
        int mid=(l+r)>>1;
        merge(a,l,mid);
        merge(a,mid+1,r);
        int i=l,j=mid+1;
        for (int k=l; k<=r; k++)
        {
            if (j>r || i<=mid && a[i]<=a[j])
                b[k]=a[i++];
            else
            {
                cnt+=mid-i+1;
                b[k]=a[j++];
            }
        }
        for (int k=l; k<=r; k++)
            a[k]=b[k];
    }
    signed main()
    {
        ios::sync_with_stdio(false);
    //  freopen("stdin.in","r",stdin);
    //  freopen("stdout.out","w",stdout);
        while(cin>>n)
        {
            int ok=0,x;
            for (i=1; i<=n*n; i++)
            {
                cin>>x;
                if (x==0)
                    ok=1;
                else
                    a[i-ok]=x;
            }
            ok=0;
            for (i=1; i<=n*n; i++)
            {
                cin>>x;
                if (x==0)
                    ok=1;
                else
                    c[i-ok]=x;
            }
            cnt=0;
            memset(b,0,sizeof(b));
            merge(a,1,n*n);
            long long ans=cnt;
            memset(b,0,sizeof(b));
            cnt=0;
            merge(c,1,n*n);
            if ((ans&1)==(cnt&1))
                puts("TAK");
            else
                puts("NIE");
        }
        return 0;
    }
    
  • 相关阅读:
    linux网络编程-socket(36)
    linux网络编程-socket(2)
    linux网络编程-socket(1)
    jni不通过线程c回调java的函数
    jni 字符串的梳理 2 字符串的处理操作
    jni 字符串的梳理
    android studio 中jni底层日志的打印
    事件冒泡与事件捕获
    盒子模型
    比较好的前端面试题
  • 原文地址:https://www.cnblogs.com/hnkjdx-ssf/p/14278840.html
Copyright © 2011-2022 走看看