zoukankan      html  css  js  c++  java
  • Hash (poj2002-Squares & poj3349-Snowflake Snow Snowflakes)

    //突然发现好弱,好多基础的算法竟然都不会,哈希这种经典的算法,我貌似基本没怎么做过相关的题0.0

    POJ2002

    题意:给n个点,问有多少组四个点能组成正方形。

    题解:枚举两个点,通过公式算出另外两个点,然后通过哈希查找另外两个点存不存在。

    公式是抄网上的,哈希直接用了vector存的,反正时限3500ms

    点的哈希就是(x^2+y^2)%MOD

    AC代码:

    /**************************************
    Memory: 924 KB        Time: 969 MS
    Language: G++        Result: Accepted
    **************************************/
    #include <cstdio>
    #include <cstring>
    #include <vector>
    
    using namespace std;
    
    const int MOD = 20007;
    const int N = 1005;
    
    struct Point {
        int x, y;
        int key;
    } p[N];
    
    int cal(int x, int y) {
        return (x*x+y*y) % MOD;
    }
    
    vector<int> vec[MOD];
    
    void insert(int x) {
        vec[p[x].key].push_back(x);
    }
    
    bool find(int x, int y) {
        int k = cal(x, y);
        for (unsigned i = 0; i < vec[k].size(); ++i) {
            int v = vec[k][i];
            if (x == p[v].x && y == p[v].y) return true;
        }
        return false;
    }
    
    int main() {
        //freopen("in", "r", stdin);
        int n;
        while (~scanf("%d", &n) && n) {
            for (int i = 0; i < MOD; ++i) vec[i].clear();
            for (int i = 0; i < n; ++i) {
                scanf("%d%d", &p[i].x, &p[i].y);
                p[i].key = cal(p[i].x, p[i].y);
                insert(i);
            }
            int ans = 0;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (i == j) continue;
                    int x1 = p[i].x-p[j].y+p[i].y;  
                    int y1 = p[i].y+p[j].x-p[i].x;
                    int x2 = p[j].x-p[j].y+p[i].y;  
                    int y2 = p[j].y+p[j].x-p[i].x;
                    if (find(x1,y1) && find(x2,y2)) ++ans;
                }
            }
            printf("%d
    ", ans/4);
        }
         return 0;
    }

      

    POJ3349

    求有没有相同的雪花,每个雪花有12中hash值,分别试一次,插入一个就可以了。时间复杂度O(n*12)。

    本来用的上面vector的,然后T了好久T^T

    后来改成了类似存图时前向星的方法,3438ms水过去了。

    #include <cstdio>
    #include <cstring>
    #include <vector>
    
    using namespace std;
    
    const int MOD = 999979;
    const int MAXN = 100010;
    const int N = 6;
    
    int snow[MAXN][N];
    int head[MOD];
    int nt[MAXN];
    int cnt;
    
    void insert(int a[], int x) {
        for (int i = 0; i < N; ++i) snow[cnt][i] = a[i];
        nt[cnt] = head[x];
        head[x] = cnt++;
    }
    
    bool find(int a[], int x) {
        //printf("%d %d
    ", x, head[x]);
        for (int i = head[x]; i != -1; i = nt[i]) {
            //printf("i=%d
    ", i); break;
            for (int j = 0; j < N; ++j) {
                if (a[j] != snow[i][j]) break;
                if (j == N-1) return true;
            }
        }
        return false;
    }
    
    int main() {
        //freopen("in", "r", stdin);
        int n;
        while (~scanf("%d", &n) && n) {
            cnt = 0;
            bool fg = false;
            memset(head, -1, sizeof head);
            int a[10], b[10];
            for (int i = 0; i < n; ++i) {
                for (int i = 0; i < N; ++i) scanf("%d", a+i);
                if (fg) continue;
                int val = 0;
                for (int i = 0; i < N; ++i) {
                    val = 0;
                    for (int j = 0; j < N; ++j) {
                        val = (val * 10 + a[(i+j)%N]) % MOD;
                        b[j] = a[(i+j)%N];
                    }
                    if (find(b, val)) { fg = true; break; }
                    val = 0;
                    for (int j = N-1; j >= 0; --j) {
                        b[N-j-1] = a[(i+j)%N];
                        val = (val * 10 + a[(i+j)%N]) % MOD;
                    }
                    if (find(b, val)) { fg = true; break; }
                }
                if(!fg)  insert(b, val);
            }
            if (fg) puts("Twin snowflakes found.");
            else puts("No two snowflakes are alike.");
            
        }
         return 0;
    }

      

  • 相关阅读:
    中缀表达式std
    后缀表达式
    取石头游戏
    LeetCode404Sum of Left Leaves左叶子之和
    LeetCode387First Unique Character in a String字符串中第一个唯一字符
    简单排列习题2.5 的 2
    周期串Uva455 P37 3-4
    【递归】分形
    【递归】普通递归关系(矩阵快速幂)
    P3486 [POI2009]KON-Ticket Inspector
  • 原文地址:https://www.cnblogs.com/wenruo/p/5794781.html
Copyright © 2011-2022 走看看