• POJ3690:Constellations(二维哈希)


    Constellations

    Time Limit: 3000MS   Memory Limit: 65536K
    Total Submissions: 6822   Accepted: 1382

    题目链接:http://poj.org/problem?id=3690

    Description:

    The starry sky in the summer night is one of the most beautiful things on this planet. People imagine that some groups of stars in the sky form so-called constellations. Formally a constellation is a group of stars that are connected together to form a figure or picture. Some well-known constellations contain striking and familiar patterns of bright stars. Examples are Orion (containing a figure of a hunter), Leo (containing bright stars outlining the form of a lion), Scorpius (a scorpion), and Crux (a cross).

    In this problem, you are to find occurrences of given constellations in a starry sky. For the sake of simplicity, the starry sky is given as a N × M matrix, each cell of which is a '*' or '0' indicating a star in the corresponding position or no star, respectively. Several constellations are given as a group of T P × Q matrices. You are to report how many constellations appear in the starry sky.

    Note that a constellation appears in the sky if and only the corresponding P × Q matrix exactly matches some P × Q sub-matrix in the N × M matrix.

    Input:

    The input consists of multiple test cases. Each test case starts with a line containing five integers N, M, T, P and Q(1 ≤ N, M ≤ 1000, 1 ≤ T ≤ 100, 1 ≤ P, Q ≤ 50). 
    The following N lines describe the N × M matrix, each of which contains M characters '*' or '0'.
    The last part of the test case describe T constellations, each of which takes P lines in the same format as the matrix describing the sky. There is a blank line preceding each constellation.
    The last test case is followed by a line containing five zeros.

    Output:

    For each test case, print a line containing the test case number( beginning with 1) followed by the number of constellations appearing in the sky.

    Sample Input:

    3 3 2 2 2
    *00
    0**
    *00
    
    **
    00
    
    *0
    **
    3 3 2 2 2
    *00
    0**
    *00
    
    **
    00
    
    *0
    0*
    0 0 0 0 0

    Sample Output:

    Case 1: 1
    Case 2: 2

    题意:

    给出一个n*m个矩阵,并且给出若干个p*q的小矩阵,然后回答有多少个小矩阵在大矩阵中出现了的。

    题解:

    数据范围不是很大,直接二维暴力hash就是了。

    二维hash跟一维都差不多的吧,具体细节见代码吧。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <set>
    using namespace std;
    typedef long long ll;
    typedef unsigned int Ull ;
    const int N = 2005;
    int n, m, T, p, q;
    Ull x1 = 1413, x2 = 12582917;
    Ull px1[N], px2[N];
    Ull Hash[N][N], Hash_Table[N * N], val[55][55];
    char s[N][N], t[N][N];
    
    int main() {
        px1[0] = px2[0] = 1;
        for(int i = 1; i <= 2000; i++) {
            px1[i] = px1[i - 1] * x1;
            px2[i] = px2[i - 1] * x2;
        }
        int cnt = 0;
        while(scanf("%d%d%d%d%d", &n, &m, &T, &p, &q) != EOF) {
            if(n + m + T + p + q <= 0)
                break ;
            cnt++;
            memset(Hash,0,sizeof(Hash));
            for(int i = 1; i <= n; i++) {
                scanf("%s", s[i] + 1);
                for(int j = 1; j <= m; j++) {
                    Hash[i][j] = Hash[i][j - 1] * x1 + (Ull)s[i][j];
                }
            }
            for(int j = 1; j <= m; j++) {
                for(int i = 1; i <= n; i++) {
                    Hash[i][j] = Hash[i - 1][j] * x2 + Hash[i][j];
                }
            }
            int tt = T;
            multiset<Ull> S;
            while(tt--) {
                memset(val,0,sizeof(val));
                for(int i = 1; i <= p; i++) {
                    scanf("%s", t[i] + 1);
                    for(int j = 1; j <= q; j++) {
                        val[i][j] = val[i][j - 1] * x1 + (Ull)t[i][j];
                    }
                }
                for(int j = 1; j <= q; j++) {
                    for(int i = 1; i <= p; i++) {
                        val[i][j] = val[i - 1][j] * x2 + val[i][j];
                    }
                }
                S.insert(val[p][q]);
            }
            for(int i = p; i <= n; i++) {
                for(int j = q; j <= m; j++) {
                    Ull Val = Hash[i][j] + Hash[i - p][j - q] * px1[q] * px2[p] - Hash[i][j - q] * px1[q] - Hash[i - p][j] * px2[p];
                    S.erase(Val);
                }
            }
            printf("Case %d: %d
    ", cnt, T - (int)S.size());
        }
        return 0;
    }
  • 相关阅读:
    从程序员到项目经理(5):程序员加油站 不是人人都懂的学习要点
    从程序员到项目经理(14):项目经理必须懂一点“章法”
    从程序员到项目经理(17):你不是一个人在战斗思维一换天地宽
    从程序员到项目经理(19):想改变任何人都是徒劳的
    tp5时间戳转换日期格式
    win10让人愤怒的磁盘占用100%问题
    uniapp将时间日期格式化的组件unidateformat的用法
    Asp.Net大型项目实践系列第二季(一)哥欲善其事,必先利其器...
    Asp.Net大型项目实践(9)ExtJs实现系统框架页(非iframe,附源码,在线demo)
    Asp.Net大型项目实践(10)基于MVC Action粒度的权限管理(在线demo,全部源码)
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10574488.html
Copyright © 2020-2023  润新知