[CSU 1923 Mysterious Block D]哈希

[CSU 1923 Mysterious Block D]哈希

分类: HashMap

1. 题目链接

[CSU 1923 Mysterious Block D]

2. 题意描述

输入一个 nm 的地图,地图中’#‘表示墙,墙将将这个地图分隔成若干个小块,每个小块都是一个矩形。每个小块中包含了’+’,’-‘两种字符。
求这个地图中有多少个不同的小块。
如果小块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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值