zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    母牛的故事
    python 实现计算数独
    java程序计算数独游戏
    《深入理解Java虚拟机》笔记7
    安装red5 1.0.1版本Java_home不能用Java7
    计算流图中的循环集合
    《深入理解Java虚拟机》笔记5
    《深入理解Java虚拟机》笔记4
    n的阶乘-编程2.md
    爬楼梯问题-斐波那契序列的应用.md
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10574488.html
Copyright © 2011-2022 走看看