1567: [JSOI2008]Blue Mary的战役地图
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 841 Solved: 483
[ Submit][ Status][ Discuss]
Description
Blue Mary最近迷上了玩Starcraft(星际争霸) 的RPG游戏。她正在设法寻找更多的战役地图以进一步提高自己的水平。 由于Blue Mary的技术已经达到了一定的高度,因此,对于用同一种打法能够通过的战役地图,她只需要玩一张,她就能了解这一类战役的打法,然后她就没有兴趣再玩儿这一类地图了。而网上流传的地图有很多都是属于同一种打法,因此Blue Mary需要你写一个程序,来帮助她判断哪些地图是属于同一类的。 具体来说,Blue Mary已经将战役地图编码为n*n的矩阵,矩阵的每个格子里面是一个32位(有符号)正整数。对于两个矩阵,他们的相似程度定义为他们的最大公共正方形矩阵的边长。两个矩阵的相似程度越大,这两张战役地图就越有可能是属于同一类的。
Input
第一行包含一个正整数n。 以下n行,每行包含n个正整数,表示第一张战役地图的代表矩阵。 再以下n行,每行包含n个正整数,表示第二张战役地图的代表矩阵。
Output
仅包含一行。这一行仅有一个正整数,表示这两个矩阵的相似程度。
Sample Input
3
1 2 3
4 5 6
7 8 9
5 6 7
8 9 1
2 3 4
1 2 3
4 5 6
7 8 9
5 6 7
8 9 1
2 3 4
Sample Output
2
HINT
样例解释:
子矩阵:
5 6
8 9
为两个地图的最大公共矩阵
约定:
n<=50
Source
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef unsigned long long UL;
const UL h1 = 131;
const UL h2 = 233;
int n,a[55][55],b[55][55];
UL ha[55][55],hb[55][55],mi1[55],mi2[55];
void hash(int (*x)[55],UL (*y)[55])
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
y[i][j] = x[i][j];
y[i][j] += y[i-1][j]*h2;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
y[i][j] += y[i][j-1]*h1;
}
UL Get(int r1,int c1,int len,UL (*h)[55])
{
int r2 = r1 + len - 1;
int c2 = c1 + len - 1;
UL ret = h[r2][c2];
ret -= mi2[len]*h[r1-1][c2];
ret -= mi1[len]*h[r2][c1-1];
ret += mi1[len]*mi2[len]*h[r1-1][c1-1];
return ret;
}
bool Judge(int now)
{
if (!now) return 1;
for (int i = 1; i <= n - now + 1; i++)
for (int j = 1; j <= n - now + 1; j++)
for (int x = 1; x <= n - now + 1; x++)
for (int y = 1; y <= n - now + 1; y++)
if (Get(i,j,now,ha) == Get(x,y,now,hb)) return 1;
return 0;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
scanf("%d",&a[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
scanf("%d",&b[i][j]);
mi1[0] = mi2[0] = 1;
for (int i = 1; i <= n; i++)
mi1[i] = mi1[i-1]*h1,mi2[i] = mi2[i-1]*h2;
hash(a,ha); hash(b,hb);
int L = 0,R = n;
while (R - L > 1) {
int mid = (L + R) >> 1;
if (Judge(mid)) L = mid;
else R = mid;
}
if (Judge(R)) cout << R;
else cout << L;
return 0;
}