• B1567 [JSOI2008]Blue Mary的战役地图 二分答案+hash


    一开始以为是dp,后来看了一下标签。。。二分答案?之前也想过,但是没往下想,然后之后的算法就顺理成章,先求出第一个地图的所有子矩阵的hash值,然后求第二个,在上一个地图例二分查找,然后就没了。

    算法很好想,也很好写,但是一开始我想的和最长公共子序列差不多的dp却不行(子矩阵是子串啊)。。。总的来说不是什么难题。

    lower_bound是大于等于,返回的时候不用减一。

    upper_bound是大于。

    题干:

    Description
    Blue Mary最近迷上了玩Starcraft(星际争霸) 的RPG游戏。她正在设法寻找更多的战役地图以进一步提高自己的水平。 由于Blue Mary的技术已经达到了一定的高度,因此,对于用同一种打法能够通过的战役地图,她只需要玩一张,她就能了解这一类战役的打法,然后她就没有兴趣再玩儿这一类地图了。而网上流传的地图有很多都是属于同一种打法,因此Blue Mary需要你写一个程序,来帮助她判断哪些地图是属于同一类的。 具体来说,Blue Mary已经将战役地图编码为n*n的矩阵,矩阵的每个格子里面是一个32位(有符号)正整数。对于两个矩阵,他们的相似程度定义为他们的最大公共正方形矩阵的边长。两个矩阵的相似程度越大,这两张战役地图就越有可能是属于同一类的。
    Input
    第一行包含一个正整数n。 以下n行,每行包含n个正整数,表示第一张战役地图的代表矩阵。 再以下n行,每行包含n个正整数,表示第二张战役地图的代表矩阵。
    Output
    仅包含一行。这一行仅有一个正整数,表示这两个矩阵的相似程度。
    Sample Input
    3
    1 2 3
    4 5 6
    7 8 9
    5 6 7
    8 9 1
    2 3 4
    Sample Output
    2
    HINT
    样例解释:
    子矩阵:
    5 6
    8 9
    为两个地图的最大公共矩阵
    
    约定:
    n<=50
    Source

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    int n,len = 0;
    ull mp[55][55],mp2[55][55],w[50000];
    bool cmp(ull a,ull b)
    {
        return a < b;
    }
    void haxi(int x,int y,int l)
    {
        ull tot = 0;
        duke(i,x,x + l - 1)
        {
            duke(j,y,y + l - 1)
            {
                tot = tot * 127 + mp[i][j];
            }
        }
        w[++len] = tot;
    }
    ull haxi2(int x,int y,int l)
    {
        ull tot = 0;
        duke(i,x,x + l - 1)
        {
            duke(j,y,y + l - 1)
            {
                tot = tot * 127 + mp2[i][j];
            }
        }
        return tot;
    }
    int main()
    {
        read(n);
        duke(i,1,n)
        duke(j,1,n)
        read(mp[i][j]);
        duke(i,1,n)
        duke(j,1,n)
        read(mp2[i][j]);
        int l = 1,r = n;
        while(l != r)
        {
            clean(w);
            len = 0;
            int mid = (l + r) >> 1;
            duke(i,1,n - mid + 1)
            {
                duke(j,1,n - mid + 1)
                {
                    haxi(i,j,mid);
                }
            }
            sort(w + 1,w + len + 1,cmp);
            int ok = 0;
            duke(i,1,n - mid + 1)
            {
                duke(j,1,n - mid + 1)
                {
                    ull p = haxi2(i,j,mid);
                    int y = lower_bound(w + 1,w + len + 1,p) - w;
                    if(w[y] == p)
                    {
                        ok = 1;
                        break;
                    }
                }
                if(ok == 1)
                    break;
            }
            if(ok == 1)
                l = mid + 1;
            else
                r = mid;
        }
        clean(w);
        len = 0;
        duke(i,1,n - l + 1)
        {
            duke(j,1,n - l + 1)
            {
                haxi(i,j,l);
            }
        }
        sort(w + 1,w + len + 1,cmp);
        int ok = 0;
        duke(i,1,n - l + 1)
        {
            duke(j,1,n - l + 1)
            {
                ull p = haxi2(i,j,l);
                int y = lower_bound(w + 1,w + len + 1,p) - w;
                if(w[y] == p)
                {
                    ok = 1;
                    break;
                }
            }
            if(ok == 1)
                break;
        }
        if(ok == 1)
        write(r);
        else
        write(r - 1);
        return 0;
    }
    /*
    3
    1 2 3
    4 5 6
    7 8 9
    5 6 7
    8 9 1
    2 3 4
    */
    /*
    5
    1 2 3 4 5
    5 6 7 8 9
    8 9 10 11 12
    1 2 3 4 5
    5 4 3 2 1
    1 2 3 5 7
    5 3 1 2 3
    1 4 5 6 7
    4 5 8 9 10
    4 7 1 5 6
    */
  • 相关阅读:
    剑指Offer_08_跳台阶
    剑指Offer_07_斐波那契数列
    HDU 4283 You Are the One
    1B. Spreadsheets
    1A Theatre Square
    HDU 2476 String painter(记忆化搜索, DP)
    LightOJ 1422 Halloween Costumes(记忆化搜索)
    POJ 1651 Multiplication PuzzleDP方法:
    POJ 2955 Brackets (区间DP)
    HDU 5452 Minimum Cut
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9538555.html
Copyright © 2020-2023  润新知