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
*/

 

posted @ 2018-08-26 20:26  DukeLv  阅读(172)  评论(0编辑  收藏  举报