BZOJ 1567 Blue Mary的战役地图(二维hash+二分)

摘要:
范围这么小可以枚举子正方形的边长。那么可以对这个矩形进行二维hash,就可以在O的时候求出任意子矩形的hash值。然后判断这些正方形的hash值有没有相同的部分就行了。需要注意的是行和列乘的hash种子值需要不同的质数,否则可能出现冲突。

题意: 求两个矩形最大公共子正方形。(n<=50)

范围这么小可以枚举子正方形的边长。那么可以对这个矩形进行二维hash,就可以在O(1)的时候求出任意子矩形的hash值。然后判断这些正方形的hash值有没有相同的

部分就行了。可以用二分来判断。

需要注意的是行和列乘的hash种子值需要不同的质数,否则可能出现冲突。

时间复杂度O(n^3logn).

BZOJ 1567 Blue Mary的战役地图(二维hash+二分)第1张BZOJ 1567 Blue Mary的战役地图(二维hash+二分)第2张
# include <cstdio># include <cstring># include <cstdlib># include <iostream># include <vector># include <queue># include <stack># include <map># include <set># include <cmath># include <algorithm>
using namespacestd;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-9# define MOD 1024523# define INF 1000000000# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int>PII;
typedef vector<int>VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long longLL;
intScan() {
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void Out(inta) {
    if(a<0) {putchar('-'); a=-a;}
    if(a>=10) Out(a/10);
    putchar(a%10+'0');
}
const int N=55;
//Code begin...

int hash1[N][N], hash2[N][N], P[N*N], Q[N*N], n;
VI a;
VI::iterator it;

bool check(intans){
    FOR(i,ans,n) FOR(j,ans,n) {
        int tmp=hash2[i][j]-hash2[i-ans][j]*Q[ans]-hash2[i][j-ans]*P[ans]+hash2[i-ans][j-ans]*P[ans]*Q[ans];
        it=lower_bound(a.begin(),a.end(),tmp);
        if (it==a.end()||*it!=tmp) continue;
        return true;
    }
    return false;
}
intmain ()
{
    scanf("%d",&n);
    P[0]=1; FOR(i,1,250) P[i]=P[i-1]*131;
    Q[0]=1; FOR(i,1,250) Q[i]=Q[i-1]*1789;
    FOR(i,1,n) FOR(j,1,n) scanf("%d",&hash1[i][j]), hash1[i][j]+=hash1[i][j-1]*P[1];
    FOR(i,1,n) FOR(j,1,n) hash1[i][j]+=hash1[i-1][j]*Q[1];
    FOR(i,1,n) FOR(j,1,n) scanf("%d",&hash2[i][j]), hash2[i][j]+=hash2[i][j-1]*P[1];
    FOR(i,1,n) FOR(j,1,n) hash2[i][j]+=hash2[i-1][j]*Q[1];
    intans;
    for (ans=n; ans>=1; --ans) {
        a.clear();
        FOR(i,ans,n) FOR(j,ans,n) a.pb(hash1[i][j]-hash1[i-ans][j]*Q[ans]-hash1[i][j-ans]*P[ans]+hash1[i-ans][j-ans]*P[ans]*Q[ans]);
        sort(a.begin(),a.end());
        if (check(ans)) break;
    }
    printf("%d
",ans);
    return 0;
}
View Code

免责声明:文章转载自《BZOJ 1567 Blue Mary的战役地图(二维hash+二分)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇启动secondarynamenode时报错人工智能-有限状态机(FSM)的学习下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

图像处理-余弦变换

什么是DCT? 一维DCT变换 一维DCT变换时二维DCT变换的基础,所以我们先来讨论下一维DCT变换。一维DCT变换共有8种形式,其中最常用的是第二种形式,由于其运算简单、适用范围广。我们在这里只讨论这种形式,其表达式如下: 其中,f(i)为原始的信号,F(u)是DCT变换后的系数,N为原始信号的点数,c(u)可以认为是一个补偿系数,可以使DCT变换矩阵...

Matlab图像处理系列4———傅立叶变换和反变换的图像

注意:这一系列实验的图像处理程序,使用Matlab实现最重要的图像处理算法 1.Fourier兑换 (1)频域增强 除了在空间域内能够加工处理图像以外,我们还能够将图像变换到其它空间后进行处理。这些方法称为变换域方法,最常见的变换域是频域。 使用Fourier变换把图像从空间域变换到频域。在频域内做对应增强处理,再从频域变换到空间域得到处理后的图像。...

二维码(QR code)基本知识

1.二维码定义:   二维码(2-Dimensional Bar Code),是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的。它是指在一维条码的基础上扩展出另一维具有可读性的条码,使用黑白矩形图案表示二进制数据,被设备扫描后可获取其中所包含的信息。一维条码的宽度记载着数据,而其长度没有记载数据。二维条码的长度、...

二维vector的使用

    和数组一样,数组有二维的数组,vector也有二维的vector。下面就介绍一下二维vector的使用方法。     一般声明初始化二维vector有三种方法     (1) vector< vector<int> > v(n,vector<int>(m));   //在声明的时候就一次性指定vector内外层的...

二维矩形装箱问题(2D rectangular packing problem, 简称2DRP)介绍

写在前面 由于某些原因,这篇文章还没写完就作者就搞别的问题去了,写到一半很不好意思,大家可以去看原文对应的论文进一步研究:【A skyline heuristic for the 2D rectangular packing and strip packing problems】。祝大家学习顺利~ 前言 今天为大家介绍二维矩形装箱问题(2D recta...

二维装箱算法

需求:把箱子装到车上 /** 策略上下文 〈装箱工具〉 @author 27381 @version V1.0 @date 2020/12/5.*/public class ContextStrategy extends Abstractloader {LoaderStrategy loaderStrategy; public ContextStr...