SYSU-7,Gym 100273J, Japanese Writing,hash
题目大意:给你一些笔画(笔画顺序打乱),让你判断两个字是不是相等的。
解:建议如果没看题的去读一读题,两个笔画相等的判断只在于两点之间的相对关系(9个方向)以及笔画的方向(8个),所以我们对每一个笔画根据他的方向压一个hash值(hash掉这个笔画两个点对于所有其他点的方向)。其实判笔画本质是一个图同构问题,类似于给定一个图的所有点的度数,如果度数全部相等,说明我们肯定能找到一个同构的图。
(吐槽一下,本来1A的,结果有几个变量手残打错了debug了半天T T,差点没把20个点的数据画出来
#include <cstdio> #include <string> #include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <complex> #include <set> #include <vector> #include <map> #include <queue> #include <deque> #include <ctime> using namespace std; const double EPS = 1e-8; #define ABS(x) ((x)<0?(-(x)):(x)) #define SQR(x) ((x)*(x)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define LSON(x) ((x)<<1) #define RSON(x) (((x)<<1)+1) #define LOWBIT(x) ((x)&(-(x))) #define MAXN 11111 #define VOIDPOINT 0 #define LL long long #define OO 214748364 #define MAXT 8 const LL MOD = 1e9+7; LL pre[MAXT], key[MAXT], preT[MAXT], keyT[MAXT]; int m, lastm; LL poww[MAXN]; struct point{ int x, y; point(int a = 0, int b = 0): x(a), y(b) {} void read() { scanf("%d%d", &x, &y); } }; int typee(const point &a, const point &b) { if (a.x == b.x && b.y > a.y) return 0; if (b.x > a.x && b.y > a.y) return 1; if (b.x > a.x && b.y == a.y) return 2; if (b.x > a.x && b.y < a.y) return 3; if (b.x == a.x && b.y < a.y) return 4; if (b.x < a.x && b.y < a.y) return 5; if (b.x < a.x && b.y == a.y) return 6; if (b.x < a.x && b.y > a.y) return 7; return 8; } struct data{ point s, t; int type; data() {} void read() { s.read(); t.read(); type = typee(s, t); } LL hash(const data &rhs) const { LL res = 0; int now, x, y, z, tt; // for (int i = 0; i < m; ++i) if (i != num) { x = rhs.type; y = typee(s, rhs.s); z = typee(s, rhs.t); tt = x * 81 + y * 9 + z; now = poww[tt]; res = (res + now) % MOD; // } // for (int i = 0; i < m; ++i) if (i != num) { x = rhs.type; y = typee(t, rhs.s); z = typee(t, rhs.t); tt = x * 81 + y * 9 + z + 729; now = poww[tt]; res = (res + now) % MOD; // } return res; } }; void pree() { poww[0] = 1; for (int i = 1; i < MAXN; ++i) { poww[i] = poww[i-1] * (729); poww[i] %= MOD; } } data a[MAXN]; void init() { scanf("%d", &m); memset(keyT, 0, sizeof(keyT)); for (int i = 0; i < m; ++i) { a[i].read(); keyT[a[i].type]++; } for (int i = 0; i < MAXT; ++i) key[i] = 1; for (int i = 0; i < m; ++i) { LL tmp = 0; for (int j = 0; j < m; ++j) if (i != j) { tmp += a[i].hash(a[j]); tmp %= MOD; } key[a[i].type] *= tmp; key[a[i].type] %= MOD; } } int main() { // freopen("test.txt", "r", stdin); freopen("japanese.in", "r", stdin); freopen("japanese.out", "w", stdout); pree(); int n; scanf("%d", &n); for (int tt = 0; tt < n; ++tt) { init(); if (tt == 0) lastm = m; if (tt) { bool flag = m == lastm; for (int i = 0; i < MAXT; ++i) { if (pre[i] != key[i] || preT[i] != keyT[i]) { flag = false; break; } } if (flag) puts("CORRECT"); else puts("INCORRECT"); } if (tt == 0) for (int i = 0; i < MAXT; ++i) pre[i] = key[i], preT[i] = keyT[i]; } fclose(stdin); fclose(stdout); return 0; }