POJ 3349 -- Snowflake Snow Snowflakes

Snowflake Snow Snowflakes
Time Limit: 4000MS Memory Limit: 65536K
Total Submissions: 45817 Accepted: 11953

Description

You may have heard that no two snowflakes are alike. Your task is to write a program to determine whether this is really true. Your program will read information about a collection of snowflakes, and search for a pair that may be identical. Each snowflake has six arms. For each snowflake, your program will be provided with a measurement of the length of each of the six arms. Any pair of snowflakes which have the same lengths of corresponding arms should be flagged by your program as possibly identical.

Input

The first line of input will contain a single integer n, 0 < n ≤ 100000, the number of snowflakes to follow. This will be followed by n lines, each describing a snowflake. Each snowflake will be described by a line containing six integers (each integer is at least 0 and less than 10000000), the lengths of the arms of the snow ake. The lengths of the arms will be given in order around the snowflake (either clockwise or counterclockwise), but they may begin with any of the six arms. For example, the same snowflake could be described as 1 2 3 4 5 6 or 4 3 2 1 6 5.

Output

If all of the snowflakes are distinct, your program should print the message:
No two snowflakes are alike.
If there is a pair of possibly identical snow akes, your program should print the message:
Twin snowflakes found.

Sample Input

2
1 2 3 4 5 6
4 3 2 1 6 5

Sample Output

Twin snowflakes found.

Source

 
 

题意:

  在n(n<10W)个雪花中判断是否存在两片完全相同的雪花(孪生雪花),每片雪花有6个角,每个角的长度限制为100W

  两片雪花相等的条件:

  雪花6个角的长度按顺序相等(这个顺序即可以是顺时针的也可以是逆时针的)

 

解题思路:

  要判断是否有两个雪花为孪生雪花,首先要明确不能两两比较,10W个雪花两两比较一定会超时

  考虑到如果两个雪花为孪生雪花,那么他们所有的角对应相等,他们所有角的长度之和也一定相等。所以可以首先判断两个雪花的角的长度之和是否相等。可以使用索引表——hash表的方式,为我们的雪花和所有角的长度之和之间建立起映射关系。

  雪花的角的长度最大为100W,所以他们的和最大为600W。经过测试,如果将哈希表的长度设置在600W,其时间复杂度如下图:

  如果将哈希表的长度设置在100W,其时间复杂度如下图:

   可见,并不是哈希表越长,产生冲突的次数越少,越会节省时间,所以我们将哈希表的长度设置为100W(即maxn)

        哈希函数即为:key = 雪花角的长度和 % 1000000

  处理冲突的方法使用链地址法

  当发生冲突时,在使用链地址法寻找当前雪花的插入地址的过程中,与已插入的雪花进行比较。

  比较的方法……首先使用数组存储雪花的六个角的长度,因为有逆时针 顺时针 还不确定起始位置,所以使用循环数组

  上代码吧

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 const __int64 maxn = 1000000;
  6 class
  7 {
  8 public:
  9     __int64 len[6];//六瓣叶子的长度
 10 }snows[100001];
 11 
 12 class HashTable{
 13 public:
 14     __int64 len[6];//六瓣叶子的长度
 15     HashTable *next;//使用链地址法处理冲突
 16     HashTable()//初始化
 17     {
 18         next = 0;
 19     }
 20 };
 21 
 22 HashTable* hashtable[maxn+1];
 23 
 24 ///用于计算hashtable的key值
 25 __int64 computeKey(int k)
 26 {
 27     __int64 key = 0;
 28     for(int i=0;i<6;i++)
 29         key += snows[k].len[i]%maxn;
 30     key = key%maxn;
 31     return ++key;//下标为0的位置我们不使用
 32 }
 33 
 34 bool compare(HashTable *temp,int k)
 35 {
 36     for(int i=0;i<6;i++)
 37     {
 38         //指定len[0]为查找的起点,
 39         //如果有长度为len[0]的花瓣则从这里开始查找,所有花瓣不全相同,则继续查找下一个长度等于len[0]的花瓣
 40         //如果没有长度为len[0]的花瓣,两片雪花肯定不同
 41         if(temp->len[i] == snows[k].len[0])
 42         {///顺时针
 43             if(temp->len[(i+1)%6] == snows[k].len[1]
 44                &&temp->len[(i+2)%6] == snows[k].len[2]
 45                &&temp->len[(i+3)%6] == snows[k].len[3]
 46                &&temp->len[(i+4)%6] == snows[k].len[4]
 47                &&temp->len[(i+5)%6] == snows[k].len[5])
 48                 return true;
 49             ///逆时针
 50             if(temp->len[(i-1+6)%6] == snows[k].len[1]
 51                &&temp->len[(i-2+6)%6] == snows[k].len[2]
 52                &&temp->len[(i-3+6)%6] == snows[k].len[3]
 53                &&temp->len[(i-4+6)%6] == snows[k].len[4]
 54                &&temp->len[(i-5+6)%6] == snows[k].len[5])
 55                 return true;
 56         }
 57     }
 58     return false;//如果两片雪花不一样,返回false
 59 }
 60 
 61 bool Insert(int k)
 62 {
 63     __int64 key = computeKey(k);
 64     if(!hashtable[key])//没有发生冲突
 65     {
 66         HashTable *temp = new HashTable;
 67         for(int i=0;i<6;i++)
 68             temp->len[i] = snows[k].len[i];
 69         hashtable[key] = temp;
 70     }else{//发生地址冲突
 71         HashTable *temp = hashtable[key];
 72         if(compare(temp,k))
 73             return true;
 74         while(temp->next)
 75         {
 76             temp = temp->next;
 77             if(compare(temp,k))
 78                 return true;
 79         }
 80         temp->next = new HashTable;//没有找到孪生雪花,将当前雪花存入hashtable
 81         for(int i=0;i<6;i++)
 82             temp->next->len[i] = snows[k].len[i];
 83     }
 84     return false;//没有找到孪生雪花
 85 }
 86 
 87 int main()
 88 {
 89     int n;
 90     while(cin>>n)
 91     {
 92         memset(hashtable,0,sizeof(hashtable));
 93         bool flag = false;///表示 还没有相同的雪花
 94         for(int i=1;i<=n;i++)
 95         {
 96             for(int j=0;j<6;j++)
 97             {
 98                 scanf("%I64d",&snows[i].len[j]);
 99             }
100             if(!flag)//如果还没有找到孪生雪花,则进行操作
101                 flag = Insert(i);
102         }
103         if(!flag)
104             cout<<"No two snowflakes are alike."<<endl;
105         else
106             cout<<"Twin snowflakes found."<<endl;
107     }
108     return 0;
109 }

 

 

转载于:https://www.cnblogs.com/yxh-amysear/p/8437058.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值