第三题:图像压缩存储
转载自博主葡萄家
描述:以二维数组表示图像,其值只有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
题目大意:题目所要求的是两个矩阵最大的相同部分。
解题思路:
可以将两个矩阵直接异或(^)出来。
0异或0等于0
1异或1等于0
0异或1等于1
(相同异或为0,不同异或为1)
两个矩阵异或之后取非。
然后题目就变成了求第三个矩阵里的最大的为1的方阵。
我们可以采用动态规划的思想。
首先从左到右遍历一次寻找每个点可以向左延伸到最远的距离。
然后从上到下遍历一次寻找每个点可以向上延伸到最远的距离。
最后直接从左上角到右下角。看直接能到最左上角的距离。
就是每个点可以延伸最大的方阵的边长。
#include<iostream>
#include<cstring>
#define maxn 1005
using namespace std;
int a[maxn][maxn];
int dp1[maxn][maxn]; //从左到右
int dp2[maxn][maxn]; //从上到下
int dp3[maxn][maxn]; //从左上角到右下角
int n;
int mi(int a,int b)
{
if(a<b) return a;
return b;
}
int ma(int a,int b)
{
if(a<b) return b;
return a;
}
int main()
{
int tes;
int i,j;
while(cin>>tes)
{
while(tes--)
{
cin>>n;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
scanf("%d",&a[i][j]);
int tmp;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
scanf("%d",&tmp);
a[i][j]=!(a[i][j]^tmp);
}
for(i=1; i<=n; i++)
{
dp1[i][0]=0;
for(j=1; j<=n; j++)
{
if(a[i][j]==1)
dp1[i][j]=dp1[i][j-1]+1;
else
dp1[i][j]=0;
}
}
for(i=1; i<=n; i++)
{
dp2[0][i]=0;
for(j=1; j<=n; j++)
{
if(a[j][i]==1)
dp2[j][i]=dp2[j-1][i]+1;
else
dp2[j][i]=0;
}
}
dp3[0][0]=0;
int res=0;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
int t=dp3[i-1][j-1];
t=mi(t,dp1[i][j-1]);
t=mi(t,dp2[i-1][j]);
if(a[i][j]==1)
dp3[i][j]=t+1;
else
dp3[i][j]=0;
res=ma(res,dp3[i][j]);
}
cout<<res<<endl;
}
}
return 0;
}