zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》 第二章 Acwing 137. 雪花雪花雪花 哈希

    地址 https://www.acwing.com/problem/content/description/139/

    有 N 片雪花,每片雪花由六个角组成,每个角都有长度。
    
    第 i 片雪花六个角的长度从某个角开始顺时针依次记为 ai,1,ai,2,…,ai,6。
    
    因为雪花的形状是封闭的环形,所以从任何一个角开始顺时针或逆时针往后记录长度,得到的六元组都代表形状相同的雪花。
    
    例如 ai,1,ai,2,…,ai,6 和 ai,2,ai,3,…,ai,6,ai,1 就是形状相同的雪花。
    
    ai,1,ai,2,…,ai,6 和 ai,6,ai,5,…,ai,1 也是形状相同的雪花。
    
    我们称两片雪花形状相同,当且仅当它们各自从某一角开始顺时针或逆时针记录长度,能得到两个相同的六元组。
    
    求这 N 片雪花中是否存在两片形状相同的雪花。
    
    输入格式
    第一行输入一个整数 N,代表雪花的数量。
    
    接下来 N 行,每行描述一片雪花。
    
    每行包含 6 个整数,分别代表雪花的六个角的长度(这六个数即为从雪花的随机一个角顺时针或逆时针记录长度得到)。
    
    同行数值之间,用空格隔开。
    
    输出格式
    如果不存在两片形状相同的雪花,则输出:
    
    No two snowflakes are alike.
    
    如果存在两片形状相同的雪花,则输出:
    
    Twin snowflakes found.
    
    数据范围
    1≤N≤100000,
    0≤ai,j<10000000
    输入样例:
    2
    1 2 3 4 5 6
    4 3 2 1 6 5
    输出样例:
    Twin snowflakes found.
    

    解答 使用哈希记录每个雪花的特征 便于比对相同雪花
    关键在于选择合适的哈希函数
    这里使用的是 将6片雪花的值的积与和相加 再%一个质数,这样相同6片雪花的值必然会得出同一个结果,然后我们再进行比对

    // 21342343254.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include <iostream>
    #include <stdio.h>
    #include <map>
    #include <vector>
    #include <memory.h>
     
    using namespace std;
    
    /*
    输出格式
    如果不存在两片形状相同的雪花,则输出:
    
    No two snowflakes are alike.
    
    如果存在两片形状相同的雪花,则输出:
    
    Twin snowflakes found.
    
    数据范围
    1≤N≤100000,
    0≤ai,j<10000000
    输入样例:
    2
    1 2 3 4 5 6
    4 3 2 1 6 5
    输出样例:
    Twin snowflakes found.
    难度:简单
    时/空限制:1s / 64MB
    总通过数:1688
    总尝试数:5413
    来源:《算法竞赛进阶指南》
    算法标签
    */
    
    
    int n;
    
    //map<long long, vector<int> > mm;
    
    int mm[100015][6];  int p = 1e5+13;
    
    int  GetHash(const int arr[6]) {
    	long long ret = 1;
    	for (int i = 0; i < 6; i++) {
    		ret *= arr[i];
    		ret %=p;
    	}
    
    	for (int i = 0; i < 6; i++) {
    		ret += arr[i];
    		ret %=p;
    	}
    
    	return ret;
    }
    
    bool check(const int a[6], const int b[6])     //判断两片雪花是否相同 
    {
    	for (int i = 0; i < 6; i++)
    		for (int j = 0; j < 6; j++)
    		{
    			bool flag = 1;
    			for (int k = 0; k < 6; k++)       //两个雪花方向上相同和相反都判一遍 
    				if (a[(i + k) % 6] != b[(j + k) % 6]) flag = 0;
    			if (flag) return 1;
    			flag = 1;
    			for (int k = 0; k < 6; k++)
    				if (a[(i + k) % 6] != b[(j - k + 6) % 6]) flag = 0;
    			if (flag) return 1;
    		}
    	return 0;
    }
    
    
    
    int main()
    {
    	scanf("%d",&n);  
        int arr[6];
    	memset(mm,-1,sizeof mm);
    	
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < 6; j++) {
    		    scanf("%d",&arr[j]);
    		}
    
    		int  hashV = GetHash(arr);
    		if (mm[hashV][0] != -1) {
    			if (check(mm[hashV], arr) == 1) {
    				cout << "Twin snowflakes found." << endl;
    				return 0;
    			}
    		}
    
            memcpy(mm[hashV] , arr, sizeof(arr[0])*6);
    		
    	}
    
    	cout << "No two snowflakes are alike." << endl;
    	return 0;
    }
    

    我的视频题解空间

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    PAT 1088. Rational Arithmetic
    PAT 1087. All Roads Lead to Rome
    PAT 1086. Tree Traversals Again
    PAT 1085. Perfect Sequence
    PAT 1084. Broken Keyboard
    PAT 1083. List Grades
    PAT 1082. Read Number in Chinese
    求最大公因数
    [转载]Latex文件转成pdf后的字体嵌入问题的解决
    [转载]Matlab有用的小工具小技巧
  • 原文地址:https://www.cnblogs.com/itdef/p/14771279.html
Copyright © 2011-2022 走看看