BZOJ 1567: [JSOI2008]Blue Mary的战役地图 矩阵二维hash
1567: [JSOI2008]Blue Mary的战役地图
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
题解:
二维hash
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<int,int> #define MP make_pair typedef long long LL; typedef unsigned long long ULL; const long long INF = 1e18+1LL; const double pi = acos(-1.0); const int N = 2e5+10, M = 1e3+20,inf = 2e9; /*inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; }*/ const ULL mod1 = 133700613937LL, mod2 = 10031LL; ULL sqr1[60],sqr2[60],ahas[60][60],bhas[60][60]; LL a[60][60],b[60][60]; int n; map<ULL, int > mp; int ok(int w) { mp.clear(); for(int i = w; i <= n; ++i) { for(int j = w; j <= n; ++j) { mp[sqr1[n - i + 1] * sqr2[n - j + 1] * (ahas[i][j] + ahas[i-w][j-w] - ahas[i-w][j] - ahas[i][j-w])] = 1; } } for(int i = w; i <= n; ++i) { for(int j = w; j <= n; ++j) { if(mp[sqr1[n - i + 1] * sqr2[n - j + 1] * (bhas[i][j] + bhas[i-w][j-w] - bhas[i-w][j] - bhas[i][j-w])]) return 1; } } return 0; } int main() { sqr1[0] = 1LL;sqr2[0] = 1LL; for(int i = 1; i <= 59; ++i) sqr1[i] = sqr1[i-1] * mod1, sqr2[i] = sqr2[i-1] * mod2; scanf("%d",&n); for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) scanf("%lld",&a[i][j]), ahas[i][j] = sqr1[i] * sqr2[j] * a[i][j], ahas[i][j] += ahas[i][j-1] + ahas[i-1][j] - ahas[i-1][j-1]; for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) scanf("%lld",&b[i][j]), bhas[i][j] = sqr1[i] * sqr2[j] * b[i][j], bhas[i][j] += bhas[i][j-1] + bhas[i-1][j] - bhas[i-1][j-1]; int ans = 0; for(int w = n; w >= 1; w--) { if(ok(w)) { printf("%d\n",w); return 0; } } printf("0\n"); return 0; }