• [JSOI2008]Blue Mary的战役地图 (二维Hash)


    [JSOI2008]Blue Mary的战役地图

    题目链接

    题目

    Blue Mary最近迷上了玩Starcraft(星际争霸) 的RPG游戏。她正在设法寻找更多的战役地图以进一步提高自己的水平。

    由于Blue Mary的技术已经达到了一定的高度,因此,对于用同一种打法能够通过的战役地图,她只需要玩一张,她就能了解这一类战役的打法,然后她就没有兴趣再玩儿这一类地图了。而网上流传的地图有很多都是属于同一种打法,因此Blue Mary需要你写一个程序,来帮助她判断哪些地图是属于同一类的。

    具体来说,Blue Mary已经将战役地图编码为n*n的矩阵,矩阵的每个格子里面是一个32位(有符号)正整数。对于两个矩阵,他们的相似程度定义为他们的最大公共正方形矩阵的边长。两个矩阵的相似程度越大,这两张战役地图就越有可能是属于同一类的。(n <= 100)

    分析

    这题可以直接暴力水过,但是通过这道题可以学习一下二维Hash
    我们可以先把一行缩为一个点,再缩列。
    代码 :

    for(int i = 1; i <= n; ++i) //行
            for(int j = 1; j <= n; ++j) 
                cin >> a[i][j], a[i][j] = (a[i][j-1]*rowbase + a[i][j]);
        for(int i = 1; i <= n; ++i) // 列
            for(int j = 1; j <= n; ++j)
                a[i][j] = (a[i][j] + a[i-1][j]*calbase);
    

    然后开个 map 存一下每个值就行了。
    还有一个重点就是计算矩阵Hash和。

    int calc1(int x, int y, int d) {
        return a[x][y] - a[x-d][y]*cal[d] - a[x][y-d]*row[d] + a[x-d][y-d]*cal[d]*row[d];
    }
    int calc2(int x, int y, int d) {
        return b[x][y] - b[x-d][y]*cal[d] - b[x][y-d]*row[d] + b[x-d][y-d]*cal[d]*row[d];
    }
    

    这个可以类比一维hash区间求和。
    然后就是完整代码了 :

    #include <bits/stdc++.h>
    #define int unsigned long long
    using namespace std;
    const int N = 105, rowbase = 11, calbase = 13;
    int a[N][N], b[N][N], row[N], cal[N], n;
    map<int, bool> p;
    int calc1(int x, int y, int d) {
        return a[x][y] - a[x-d][y]*cal[d] - a[x][y-d]*row[d] + a[x-d][y-d]*cal[d]*row[d];
    }
    int calc2(int x, int y, int d) {
        return b[x][y] - b[x-d][y]*cal[d] - b[x][y-d]*row[d] + b[x-d][y-d]*cal[d]*row[d];
    }
    signed main() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        cin >> n;
        row[0] = cal[0] = 1;
        for(int i = 1; i <= n; ++i) row[i] = row[i-1]*rowbase, cal[i] = cal[i-1]*calbase; 
        for(int i = 1; i <= n; ++i) //行
            for(int j = 1; j <= n; ++j) 
                cin >> a[i][j], a[i][j] = (a[i][j-1]*rowbase + a[i][j]);
        for(int i = 1; i <= n; ++i) // 列
            for(int j = 1; j <= n; ++j)
                a[i][j] = (a[i][j] + a[i-1][j]*calbase);
        for(int d = 0; d <= n; ++d)
            for(int i = d; i <= n; ++i)
                for(int j = d; j <= n; ++j)
                    p[calc1(i, j, d)] = 1;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                cin >> b[i][j], b[i][j] = (b[i][j-1]*rowbase + b[i][j]);
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                b[i][j] = (b[i][j] + b[i-1][j]*calbase);
        for(int d = n; d >= 0; --d)
            for(int i = d; i <= n; ++i)
                for(int j = d; j <= n; ++j)
                    if(p.find(calc2(i, j, d)) != p.end()) 
                        return cout << d, 0;
        return 0;
    }
    
  • 相关阅读:
    离散数学--第十章 群,环,域
    离散数学--十一章 格与布尔代数
    matplotlib 基础|笔记
    CF Round #632 div2
    Codeforces Round#630 div2
    PVZ 2--攻略合集?
    【POJ
    【POJ
    【Aizu
    【Aizu
  • 原文地址:https://www.cnblogs.com/DZN2004/p/13404140.html
Copyright © 2020-2023  润新知