B1567 [JSOI2008]Blue Mary的战役地图 二分答案+hash
一开始以为是dp,后来看了一下标签。。。二分答案?之前也想过,但是没往下想,然后之后的算法就顺理成章,先求出第一个地图的所有子矩阵的hash值,然后求第二个,在上一个地图例二分查找,然后就没了。
算法很好想,也很好写,但是一开始我想的和最长公共子序列差不多的dp却不行(子矩阵是子串啊)。。。总的来说不是什么难题。
lower_bound是大于等于,返回的时候不用减一。
upper_bound是大于。
题干:
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
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef unsigned long long ull; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } int n,len = 0; ull mp[55][55],mp2[55][55],w[50000]; bool cmp(ull a,ull b) { return a < b; } void haxi(int x,int y,int l) { ull tot = 0; duke(i,x,x + l - 1) { duke(j,y,y + l - 1) { tot = tot * 127 + mp[i][j]; } } w[++len] = tot; } ull haxi2(int x,int y,int l) { ull tot = 0; duke(i,x,x + l - 1) { duke(j,y,y + l - 1) { tot = tot * 127 + mp2[i][j]; } } return tot; } int main() { read(n); duke(i,1,n) duke(j,1,n) read(mp[i][j]); duke(i,1,n) duke(j,1,n) read(mp2[i][j]); int l = 1,r = n; while(l != r) { clean(w); len = 0; int mid = (l + r) >> 1; duke(i,1,n - mid + 1) { duke(j,1,n - mid + 1) { haxi(i,j,mid); } } sort(w + 1,w + len + 1,cmp); int ok = 0; duke(i,1,n - mid + 1) { duke(j,1,n - mid + 1) { ull p = haxi2(i,j,mid); int y = lower_bound(w + 1,w + len + 1,p) - w; if(w[y] == p) { ok = 1; break; } } if(ok == 1) break; } if(ok == 1) l = mid + 1; else r = mid; } clean(w); len = 0; duke(i,1,n - l + 1) { duke(j,1,n - l + 1) { haxi(i,j,l); } } sort(w + 1,w + len + 1,cmp); int ok = 0; duke(i,1,n - l + 1) { duke(j,1,n - l + 1) { ull p = haxi2(i,j,l); int y = lower_bound(w + 1,w + len + 1,p) - w; if(w[y] == p) { ok = 1; break; } } if(ok == 1) break; } if(ok == 1) write(r); else write(r - 1); return 0; } /* 3 1 2 3 4 5 6 7 8 9 5 6 7 8 9 1 2 3 4 */ /* 5 1 2 3 4 5 5 6 7 8 9 8 9 10 11 12 1 2 3 4 5 5 4 3 2 1 1 2 3 5 7 5 3 1 2 3 1 4 5 6 7 4 5 8 9 10 4 7 1 5 6 */
只想找一个不会伤害我的人