描述:
以二维数组表示图像,其值只有0、1两种,寻找两幅图像中最大的相同部分
输入:
第一行输入一个n,接下来的2n行输入两个n * n数组,寻找一个最大的m * m子区域,使得两个数组在该子区域完全相同
输出:
输出上述m
样例输入:
4
1 1 1 1
1 1 1 0
1 1 1 0
1 1 1 1
0 1 1 1
0 1 1 1
0 1 1 1
0 1 1 0
样例输出:
2
上述两个4阶数组中的一个2阶子区域(第1、2行,第2、3列完全相同)
首先通过异或运算求出表示相同部分的矩阵来,一算运算后取反,即数组中值为1表示相同部分。然后遍历该数组(dp[i][j]表示以(i,j)点为右下顶点的最大正方形的边长),利用动态转移方程:dp[i][j]=min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1(if异或出来的矩阵值为1),其动态转移方程的含义为该点的左边点、上边点、左上点中最小边长的正方形与该点才可构成全为1的正方形。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int a[maxn][maxn],b[maxn][maxn],dp[maxn][maxn];
int main() {
int n,tmp;
cin>>n;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
cin>>a[i][j];
}
}
for(int i=1; i<=n; i++) { //异或运算存储
for(int j=1; j<=n; j++) {
cin>>tmp;
tmp=a[i][j]^tmp;
b[i][j]=!tmp;
}
}
memset(dp,0,sizeof(dp));
int max=0;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
if(b[i][j]==1) {
dp[i][j]=min(min(dp[i-1][j],dp[i-1][j-1]),dp[i][j-1])+1;
if(dp[i][j]>max) {
max=dp[i][j];
}
}
}
}
cout<<max<<endl;
}