题目

求两个正方形矩阵的最大公共正方形矩阵边长


分析

第一种就是\(dp\):

设\(dp[x1][y1][x2][y2]\)表示第一个正方形矩阵以\((x1,y1)\)为右下角,

第二个正方形矩阵以\((x2,y2)\)为右下角所能得到的最大公共正方形矩阵边长

状态转移方程比较显然

第二种是二分:

二分答案,然后预处理和哈希,时间复杂度\(O(n^2log_2n)\)


代码(dp)

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=51;
int n,a[N][N],b[N][N],ans,dp[N][N][N][N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline signed min(int a,int b){return a<b?a:b;}
inline signed max(int a,int b){return a>b?a:b;}
signed main(){
n=iut();
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j) a[i][j]=iut();
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j) b[i][j]=iut();
for (rr int ia=1;ia<=n;++ia)
for (rr int ja=1;ja<=n;++ja)
for (rr int ib=1;ib<=n;++ib)
for (rr int jb=1;jb<=n;++jb)
if (a[ia][ja]==b[ib][jb]){
rr int t=min(dp[ia][ja-1][ib][jb-1],dp[ia-1][ja][ib-1][jb]);
dp[ia][ja][ib][jb]=min(dp[ia-1][ja-1][ib-1][jb-1],t)+1;
ans=max(ans,dp[ia][ja][ib][jb]);
}
return !printf("%d",ans);
}

代码(二分)

#include <cstdio>
#include <cctype>
#include <unordered_map>
#define rr register
using namespace std;
typedef unsigned uit;
const uit N=51,bas0=4177,bas1=3977;
unordered_map<uit,bool>uk; int n,a[2][N][N];
uit p1[N],p2[N],h[2][N][N],s[N][N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void doit(int t,int m){
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j)
s[i][j]=s[i][j-1]*bas0+a[t][i][j];
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n-m+1;++j)
h[t][i][j]=s[i][j+m-1]-s[i][j-1]*p1[m];
for (rr int j=1;j<=n-m+1;++j)
for (rr int i=1;i<=n;++i)
s[i][j]=s[i-1][j]*bas1+h[t][i][j];
for (rr int j=1;j<=n-m+1;++j)
for (rr int i=1;i<=n-m+1;++i)
h[t][i][j]=s[i+m-1][j]-s[i-1][j]*p2[m];
}
inline bool check(int m){
doit(0,m),doit(1,m),uk.clear();
for (rr int i=1;i<=n-m+1;++i)
for (rr int j=1;j<=n-m+1;++j) uk[h[0][i][j]]=1;
for (rr int i=1;i<=n-m+1;++i)
for (rr int j=1;j<=n-m+1;++j)
if (uk[h[1][i][j]]) return 1;
return 0;
}
signed main(){
n=iut(),p1[0]=p2[0]=1;
for (rr int i=1;i<=n;++i) p1[i]=p1[i-1]*bas0;
for (rr int i=1;i<=n;++i) p2[i]=p2[i-1]*bas1;
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j) a[0][i][j]=iut();
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j) a[1][i][j]=iut();
rr int l=1,r=n;
while (l<r){
rr int mid=(l+r+1)>>1;
if (check(mid)) l=mid;
else r=mid-1;
}
return !printf("%d",l);
}

#二分,哈希 or dp#洛谷 4398 [JSOI2008]Blue Mary的战役地图的更多相关文章

  1. BZOJ 1567: [JSOI2008]Blue Mary的战役地图( 二分答案 + hash )

    二分答案, 然后用哈希去判断... ------------------------------------------------------------------------- #include ...

  2. [JSOI2008]Blue Mary的战役地图(二分+哈希)

    Blue Mary最近迷上了玩Starcraft(星际争霸) 的RPG游戏.她正在设法寻找更多的战役地图以进一步提高自己的水平. 由于Blue Mary的技术已经达到了一定的高度,因此,对于用同一种打 ...

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

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

  4. 【矩阵哈希】【二分答案】【哈希表】bzoj1567 [JSOI2008]Blue Mary的战役地图

    引用题解:http://hzwer.com/5153.html 当然,二分可以换成哈希表. #include<cstdio> #include<iostream> #inclu ...

  5. BZOJ1567 [JSOI2008]Blue Mary的战役地图 二分答案 哈希

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1567 题意概括 给出两个n*n的数字矩阵,问最大公共正方形边长. 题解 先二分答案一个m,对于每一 ...

  6. 洛谷P4254 [JSOI2008]Blue Mary开公司(李超线段树)

    题面 传送门 题解 李超线段树板子 具体可以看这里 //minamoto #include<bits/stdc++.h> #define R register #define fp(i,a ...

  7. [JSOI2008]Blue Mary的战役地图——全网唯一一篇dp题解

    全网唯一一篇dp题解 网上貌似全部都是哈希+二分(反正我是大概baidu了翻了翻)(还有人暴力AC了的..) 哈希还是相对于dp还是比较麻烦的. 而且正确性还有可能被卡(当然这个题不会) 而且还容易写 ...

  8. bzoj 1567: [JSOI2008]Blue Mary的战役地图【二分+hash】

    二维哈希+二分 说是二维,其实就是先把列hash了,然后再用列的hash值hash行,这样可以O(n)的计算一个正方形的hash值,然后二分边长,枚举左上角点的坐标然后hash判断即可 只要base选 ...

  9. BZOJ1567 [JSOI2008]Blue Mary的战役地图(二分+二维hash)

    题意 问边长为n的两个正方形中最大的相等子正方形.(n<=50) 题解 用到了二维hash,感觉和一维的不太一样. 对于列行有两个不同的进制数然后也是通过类似前缀和的方法差分出一个矩形的hash ...

  10. Luogu P4398 [JSOI2008]Blue Mary的战役地图 矩阵哈希

    其实可以二分矩阵边长但是我太懒了$qwq$. 把每个子矩阵扔到$map$里,然后就没了 #include<cstdio> #include<map> #include<i ...

随机推荐

  1. 美团面试:说说OOM三大场景和解决方案? (绝对史上最全)

    首先,咱们先聊聊,什么是OOM? 小伙伴们,有没有遇到过程序突然崩溃,然后抛出一个OutOfMemoryError的异常?这就是我们俗称的OOM,也就是内存溢出.简单来说,就是你的Java应用想要的内 ...

  2. VS Code实现SSH远程开发

    最近收获一台新台式机,但是个人主要还是使用自己的笔记本,用了几天远程控制,感觉各种不方便,最终决定配置一下VS Code实现SSH远程开发,特此记录. 首先介绍一下环境,控制端是Windows 11, ...

  3. 【Azure 应用服务】App Service与Application Gateway组合使用时发生的域名跳转问题如何解决呢?

    问题描述 为App Service配置了应用服务网关(Application Gateway),并且为Application Gateway配置了自定义域名,通过浏览器访问时,出现域名跳转问题,由自定 ...

  4. Volatile关键字原理

    转载请标明:https://www.cnblogs.com/tangZH/p/15113505.html 一.如果一个变量被volatile关键字修饰,那么所有线程都是可见的.所谓可见就是,当一条线程 ...

  5. (广州南沙)vue知识点整理2021,主要是防止忘记防备快速翻看

         ///////////////////////////   vue 中使用路由技巧:router //////////////////////////////// 写笔记说明,之前在江门工作 ...

  6. Redis 常见数据类型(对象类型)和应用案列

    前言: 每次你在游戏中看到玩家排行榜,或者在音乐应用中浏览热门歌单,有没有想过这个排行榜是如何做到实时更新的?当然,依靠 Redis 即可做到. 在技术领域,我们经常听到「键值存储」 这个词.但在 R ...

  7. Java处理子父级菜单的方式二

    处理存在子父级关系的数据是写代码的过程中常见的操作,前面讲解过使用递归的方法来做, 可以参考这篇博客 https://www.cnblogs.com/yilangcode/p/16831867.htm ...

  8. python中记录打印的log模块logging的用法实例

    日志基础教程   日志是对软件执行时所发生事件的一种追踪方式.软件开发人员对他们的代码添加日志调用,借此来指示某事件的发生.一个事件通过一些包含变量数据的描述信息来描述(比如:每个事件发生时的数据都是 ...

  9. springboot listener、filter登录实战

    转载自: www.javaman.cn 博客系统访问: http://175.24.198.63:9090/front/index 登录功能 1.前端页面 采用的是layui-admin框架,文中的验 ...

  10. 【开源库推荐】#5 Android高亮引导库

    原文:[开源库推荐]#5 Android高亮引导库 - Stars-One的杂货小窝 本文介绍2个高亮引导库HighLightPro和Curtain hyy920109/HighLightPro: A ...