[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
Sample Output
2
HINT
样例解释:
子矩阵:
5 6
8 9
为两个地图的最大公共矩阵
约定:
n<=50
解法:先对两个矩阵hash,然后枚举最大长度,从大到小枚举。把第一个矩阵的所有情况插到哈希表中,然后查询第二个矩阵的所有情况,我用的set,也可以用vector然后去二分check。
//BZOJ 1567
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const int maxn = 60;
const int mod = 999997;
const uLL BASE1 = 1333;
const uLL BASE2 = 23333;
int m;
uLL hash1[maxn][maxn], hash2[maxn][maxn];
uLL base1[maxn], base2[maxn];
set <uLL> s;
void input()
{
scanf("%d", &m);
for(int i = 1; i <= m; i++){
for(int j = 1; j <= m; j++){
scanf("%lld", &hash1[i][j]);
}
}
for(int i = 1; i <= m; i++){
for(int j = 1; j <= m; j++){
scanf("%d", &hash2[i][j]);
}
}
for(int i = 1; i <= m; i++){
for(int j = 1; j <= m; j++){
hash1[i][j] += hash1[i-1][j]*BASE1;
hash2[i][j] += hash2[i-1][j]*BASE1;
}
}
for(int i = 1; i <= m; i++){
for(int j = 1; j <= m; j++){
hash1[i][j] += hash1[i][j-1]*BASE2;
hash2[i][j] += hash2[i][j-1]*BASE2;
}
}
base1[0] = base2[0] = 1;
for(int i = 1; i <= m; i++){
base1[i] = base1[i-1]*BASE1;
base2[i] = base2[i-1]*BASE2;
}
}
void work()
{
s.clear();
int ans, flag = 0;
for(ans = m; ans; ans--){
for(int i = ans; i <= m; i++){
for(int j = ans; j <= m; j++){
uLL h = hash1[i][j];
h -= hash1[i-ans][j]*base1[ans];
h -= hash1[i][j-ans]*base2[ans];
h += hash1[i-ans][j-ans]*base1[ans]*base2[ans];
//h %= mod;
s.insert(h);
}
}
for(int i = ans; i <= m; i++){
for(int j = ans; j <= m; j++){
uLL h = hash2[i][j];
h -= hash2[i-ans][j]*base1[ans];
h -= hash2[i][j-ans]*base2[ans];
h += hash2[i-ans][j-ans]*base1[ans]*base2[ans];
//h %= mod;
if(s.find(h) != s.end()){
flag = 1;
break;
}
}
if(flag) break;
}
if(flag) break;
}
if(flag) cout << ans << endl;
else cout << 0 << endl;
}
void output()
{
}
int main()
{
input();
work();
}