首页 > 学院 > 开发设计 > 正文

bzoj 1567: [JSOI2008]Blue Mary的战役地图 (二分+hash)

2019-11-08 02:13:01
字体:
来源:转载
供稿:网友

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

Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 882  Solved: 507[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

31 2 34 5 67 8 95 6 78 9 12 3 4

Sample Output

2

HINT

样例解释:子矩阵:5 68 9为两个地图的最大公共矩阵约定:n<=50

Source

[Submit][Status][Discuss]
HOME Back

题解:二分+hash

二分答案,然后利用hash值判定,做法十分的暴力,但是时间复杂度不是严格的,所以过掉了。

其实可以预处理出第一个大矩阵的所以小矩阵,然后二分查找。

#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<cstdio>#define ull unsigned long long#define p 2000001001#define N 53using namespace std;ull a[N][N][N],b[N][N][N],mi[N];int mpa[N][N],mpb[N][N],n;bool check(int x){	for (int i=1;i<=n-x+1;i++)	 for (int j=1;j<=n-x+1;j++)	  for (int k=1;k<=n-x+1;k++)	   for (int l=1;l<=n-x+1;l++) {	   	 bool pd=true;	   	 for (int t=1;t<=x;t++) 	   	 	if (a[i+t-1][j][j+x-1]!=b[k+t-1][l][l+x-1]) {	   	 	 //cout<<a[i][j][j-x+1]<<" "<<b[k][l][l+x-1]<<endl;	   	 	 pd=false;			 break;	 		    }		// if (pd) cout<<i<<" "<<j<<" "<<k<<" "<<l<<endl;		 if (pd) return 1;	   }	return 0;}int main(){	freopen("a.in","r",stdin);	freopen("my.out","w",stdout);	scanf("%d",&n);	for (int i=1;i<=n;i++) 	 for (int j=1;j<=n;j++) scanf("%d",&mpa[i][j]);	for (int i=1;i<=n;i++)	 for (int j=1;j<=n;j++) scanf("%d",&mpb[i][j]);	for (int i=1;i<=n;i++)	 for (int j=1;j<=n;j++) {	 	a[i][j][j]=mpa[i][j]*p;	 	for (int k=j+1;k<=n;k++)	 	 a[i][j][k]=a[i][j][k-1]*p+mpa[i][k];	 }	for (int i=1;i<=n;i++) 	 for (int j=1;j<=n;j++) {	 	b[i][j][j]=mpb[i][j]*p;	 	for (int k=j+1;k<=n;k++) 	 	 b[i][j][k]=b[i][j][k-1]*p+mpb[i][k];	 }	int l=1; int r=n; int ans=0;	while (l<=r) {		int mid=(l+r)/2;		if (check(mid)) ans=max(ans,mid),l=mid+1;		else r=mid-1;	}	PRintf("%d/n",ans);}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表