题目

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


分析

第一种就是\(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. FastGateway 发布v0.0.0.5

    FastGateway 发布v0.0.0.5 修复构建错误 修复docker-compose执行目录 修改请求来源分析数据列表展示 update README.md. 增加默认证书 修复构建脚本目录错 ...

  2. FFmpeg开发笔记(十一):ffmpeg在移植到海思HI35xx平台之将ffmpeg库引入到sample的demo中

    前言   上一篇交叉编译了ffmpeg的海思版本,使用交叉编译的qt的ffmpeg播放器在海思上播放,本片是将ffmpeg的环境添加进海思的sample环境中.   在海思sample中引入ffmpe ...

  3. 01、etcd基础介绍

    互联网技术发展真的快,层出不穷的新技术.最近项目使用到了etcd,自己之前在部署k8s集群的时候玩过,但是并没有系统的学习.正好趁这个机会,系统性的学习下.文章中的内容有些是来自官方文档,有些是来自网 ...

  4. logback中使用MDC自定义日志输出格式

    logback-MDC 相当于自定义日志格式输出 写在过滤器中 示例: try { Context context = createContext(request, response); proces ...

  5. 【Azure 存储服务】存储在Azure Storage Table中的数据,如何按照条件进行删除呢?

    问题描述 如何按条件删除 Storage Table 中的数据,如果Table中有大量的条记录需要删除,Java代码如何按条件删除 Table中的数据(Entity)? (通过Azure Storag ...

  6. Netty笔记(3) - 核心组件

    各组件关系示意图: Bootstrap 和 ServerBootstrap 说明: Bootstrap 意思是引导,一个 Netty 应用通常由一个 Bootstrap 开始,主要作用是配置整个 Ne ...

  7. Java 练习题 5岁的狗按人的年龄计算的话,前两年每一年是人的 10.5岁,之后每一年 * 增加4岁。如果5岁的狗、相当于人的多少年龄 * 10.5 + 10.5 + 4 +4 +4=33岁

    1 /*** 2 * 练习题 3 * 5岁的狗按人的年龄计算的话,前两年每一年是人的 10.5岁,之后每一年 4 * 增加4岁.如果5岁的狗.相当于人的多少年龄 5 * 10.5 + 10.5 + 4 ...

  8. markdown 一键上传发布

    工具介绍 工具由来 对于程序员等常常需要写文档的人来说,将本地markdown文档同步到云端博客平台,是一件比较繁琐的事情,首当其冲的是,大量的本地图片需要"互联网"化,即使网络上 ...

  9. Linux 网络编程从入门到进阶 学习指南

    前言 大家好,我是小康.在上一篇文章中,我们探讨了 Linux 系统编程的诸多基础构件,包括文件操作.进程管理和线程同步等,接下来,我们将视野扩展到网络世界.在这个新篇章里,我们要让应用跳出单机限制, ...

  10. $help console 里面的入口帮助文档

    $help console 里面的入口帮助文档 Object.defineProperty(window, '$help', { get: function() { // 这里面this是window ...