1567: [JSOI2008]Blue Mary的战役地图

1567: [JSOI2008]Blue Mary的战役地图

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 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

Sample Output

2

HINT

样例解释:

子矩阵:
5 6
8 9
为两个地图的最大公共矩阵

约定:
n<=50

Source

[ Submit][ Status][ Discuss]

二分一个答案,枚举矩形的左上角
二维hash没得说了。。
#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值