[CSU 1923 Mysterious Block D]哈希
分类: HashMap
1. 题目链接
2. 题意描述
输入一个
n∗m
的地图,地图中’#‘表示墙,墙将将这个地图分隔成若干个小块,每个小块都是一个矩形。每个小块中包含了’+’,’-‘两种字符。
求这个地图中有多少个不同的小块。
如果小块a经过若干次翻转90度之后,能够形成小块b,则小块a与小块b是相同的。
(3<=r,c<=111)
3. 解题思路
水题。
直接对每个小块进行四个方向地Hash即可。
4. 实现代码
#include <queue>
#include <stack>
#include <ctime>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef long double LB;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef vector<int> VI;
const int INF = 0x3f3f3f3f;
const LL INFL = 0x3f3f3f3f3f3f3f3fLL;
void debug() { cout << endl; }
template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); }
const int MAXN = 111 + 2;
const int HASH_MAX = 1000007;
const int HASH_SIZ = 1e5 + 5;
const int BASE = 131;
struct HashMap {
struct Edge {
ULL d[4];
int next;
Edge() {}
Edge(ULL dx[], int nxt) : next(nxt) { for(int i = 0; i < 4; ++i) d[i] = dx[i]; }
} edge[HASH_SIZ];
int head[HASH_MAX], tot;
void hash_init() {
tot = 0;
memset(head, -1, sizeof(head));
}
bool hash_query(ULL dx[4]) {
sort(dx, dx + 4);
ULL x = (dx[0] & dx[1] & dx[2] & dx[3]);
ULL u = x % HASH_MAX;
for(int i = head[u]; ~i; i = edge[i].next) {
bool equ = true;
for(int j = 0; j < 4; ++j) {
if(dx[j] != edge[i].d[j]) { equ = false; break; }
}
if(equ) return true;
}
return false;
}
ULL hash_add(ULL dx[4]) {
sort(dx, dx + 4);
ULL x = (dx[0] & dx[1] & dx[2] & dx[3]);
ULL u = x % HASH_MAX;
for(int i = head[u]; ~i; i = edge[i].next) {
bool equ = true;
for(int j = 0; j < 4; ++j) {
if(dx[j] != edge[i].d[j]) { equ = false; break; }
}
if(equ) return x;
}
edge[tot] = Edge(dx, head[u]);
head[u] = tot ++;
return x;
}
} hash_xxw;
int n, m;
char maze[MAXN][MAXN];
bool vis[MAXN][MAXN];
void dfs(int x, int y, int& xx, int& yy) {
if(x >= n || y >= m) return;
if(vis[x][y] || maze[x][y] == '#') return;
vis[x][y] = true;
xx = max(x, xx), yy = max(y, yy);
dfs(x + 1, y, xx, yy);
dfs(x, y + 1, xx, yy);
}
ULL up(int sx, int sy, int tx, int ty) {
ULL ret = 0;
for(int i = sx; i <= tx; ++i) {
for(int j = sy; j <= ty; ++j) {
ret = ret * BASE + (maze[i][j] == '+');
}
}
return ret;
}
ULL right(int sx, int sy, int tx, int ty) {
ULL ret = 0;
for(int j = sy; j <= ty; ++j) {
for(int i = tx; i >= sx; --i) {
ret = ret * BASE + (maze[i][j] == '+');
}
}
return ret;
}
ULL down(int sx, int sy, int tx, int ty) {
ULL ret = 0;
for(int i = tx; i >= sx; --i) {
for(int j = ty; j >= sy; --j) {
ret = ret * BASE + (maze[i][j] == '+');
}
}
return ret;
}
ULL left(int sx, int sy, int tx, int ty) {
ULL ret = 0;
for(int j = ty; j >= sy; --j) {
for(int i = sx; i <= tx; ++i) {
ret = ret * BASE + (maze[i][j] == '+');
}
}
return ret;
}
int main() {
#ifdef ___LOCAL_WONZY___
freopen ("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
while(~scanf("%d %d", &n, &m)) {
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; ++i) {
scanf("%s", maze[i]);
}
int xx, yy;
ULL dx[4];
hash_xxw.hash_init();
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
if(maze[i][j] == '#' || vis[i][j]) continue;
xx = i, yy = j;
dfs(i, j, xx, yy);
dx[0] = up(i, j, xx, yy);
dx[1] = right(i, j, xx, yy);
dx[2] = down(i, j, xx, yy);
dx[3] = left(i, j, xx, yy);
hash_xxw.hash_add(dx);
}
}
printf("%d\n", hash_xxw.tot);
}
#ifdef ___LOCAL_WONZY___
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // ___LOCAL_WONZY___
return 0;
}