三角形(哈希函数)

实验任务

给你 n 个三角形,每个三角形有一个优雅值, 然后给出一个询问,每次询问一个三角形, 求与询问的三角形,相似的三角形中的优雅值最大是多少。

★数据输入

第一行输入包括 n 一个数字,
接下来 n 行,每行四个整数数字
a,b,c,val 表示三条边,以及优美值
之后输入一个数字 m
之后 m 行,每行三个数字 a,b,c,表示询问的三角形。

★数据输出

输出 m 行,如果查询的三角形不在给定的 n 个中,输出”Sorry”,否则输出三角 形的优美值

解题思路:对于三角形三条边用哈希函数首先就是要找到一个函数找到key,三角形可以根据他们的gcd值来区分是否相似(还会有一些重合),对于重合情况,可以通过每一个key中设置一个链表,直接对比三条边是否会相等从而得出结果。(p:我实现了好几次还没有过,结果出来了但是还是RE,就先讲思路,贴评优同学的代码)

代码

 
             
             
            #include<stdio.h>
#include<algorithm>
using namespace std;
int fun(int a,int b)
{
	int t;
	while(b)
	{
		t = a%b;
		a = b;
		b = t;
	}
	return a;
}
struct tr
{
	int a,b,c;
	int val;
	tr *next;
}*tri[300005];
int main()
{
   int pai[5],n,m,i,j;
   scanf("%d",&n);
   for(i=1;i<300005;i++)
   {
   	  tri[i]=new struct tr;
   	 // tr temp=*tri[i];
   	  tri[i]->next=NULL;
   	  tri[i]->val=-0x7f;
   	  tri[i]->a=tri[i]->b=tri[i]->c=0;
   }
   for(i=1;i<=n;i++)
   {
   	  int val;
   	  scanf("%d%d%d%d",&pai[1],&pai[2],&pai[3],&val);
   	  sort(pai+1,pai+4);
   	  int gcd=fun(fun(pai[1],pai[2]),pai[3]);
   	  pai[1]/=gcd;
   	  pai[2]/=gcd;
   	  pai[3]/=gcd;
   	  int hash=pai[1]+pai[2]+pai[3];
   	  tr *p=tri[hash];
   	  for(;;)
   	  {     
   	  	   if(p->a==0&&p->b==0&&p->c==0)
   	  	   {
   	  		   p->a=pai[1];
   	  		   p->b=pai[2];
   	  		   p->c=pai[3];
   	  		   p->val=val;
   	  		   p->next=new struct tr;
   	  		   p=p->next;
   	  		   p->a=p->b=p->c=0;
   	  		   p->val=-0x3f;
   	  		   p->next=NULL;
					break;
			 }
			else if(p->a==pai[1]&&p->b==pai[2]&&p->c==pai[3])
			{
				p->val=val> p->val?val:p->val;break;
			}
			else p=p->next;
		 }
   }
   scanf("%d",&m);
   for(i=1;i<=m;i++)
   {
   	  scanf("%d%d%d",&pai[1],&pai[2],&pai[3]);
   	  sort(pai+1,pai+4);
   	  int hash=0;
   	  int gcd=fun(fun(pai[1],pai[2]),pai[3]);
		 pai[1]/=gcd;
		 pai[2]/=gcd;
		 pai[3]/=gcd; 
   	  hash=pai[1]+pai[2]+pai[3];
   	  tr *p=tri[hash];
   	  int pan=0;
   	  for(;;)
   	  {
   	  	if(p->next==NULL) break;
   	  	 if(p->a==pai[1]&&p->b==pai[2]&&p->c==pai[3])
   	  	{
   	  		printf("%d\n",p->val);pan++;break;
			  }
			  else p=p->next; 
		 }
		 if(pan==0) printf("Sorry\n");
   }
}
        
        
        

对于需要链表的题目,不知道有没有同学和我一样比较不熟悉,我觉得这份代码在链表指针上的使用比较有助于对链表的进一步理解(谢谢泽波同学给予的帮助)。

贴上我的代码:

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
using namespace std;
#define Maxsize 100005
#define INF 100000000
typedef struct atri* Tri;
typedef struct atri
{
	int a[3];
	int val;
	Tri next;
}Atri;
//typedef struct atriList* Head;
//typedef struct atriList
//{
//	Tri fir_tri;
//};

//求gcd函数 
int gcd(int a, int b)
{
	if (a<b)
	{
		int tmp = a; a = b; b = tmp;
	}
	int tmp=1;
	while (b != 0)
	{
		tmp = b;
		b = a%b;
		a = tmp;
	}
	return tmp;
}
void Init(Tri tris[Maxsize])
{
	int i;
	for (i = 0; i<Maxsize; i++)
	{
		tris[i] = new Atri;
		tris[i]->a[0] = tris[i]->a[1] = tris[i]->a[2] = 0;
		tris[i]->next = NULL;
		tris[i]->val = -INF;
	}
}
Tri tris[Maxsize];

int main()
{
	int n, m, i, j;
	int a[3], val;
	int gcdof;
	Init(tris);
	scanf("%d", &n);
	for (i = 0; i<n; i++)
	{
		scanf("%d%d%d%d", &a[0], &a[1], &a[2], &val);
		sort(a, a + 3);
		gcdof = gcd(a[0], gcd(a[1], a[2]));
		a[0] /= gcdof; a[1] /= gcdof; a[2] /= gcdof;
		Tri link = tris[a[0] + a[1] + a[2]]->next;                         //link代表这个key值的链表头指针 
		int exist = 0;                                               //设置初始该相似三角形在链表中不存在时为0;
		if (link!= NULL)
		{
			while (1)
			{
				if (link->a[0] == a[0] && link->a[1] == a[1] && link->a[2] == a[2])
				{
					if (link->val < val)link->val = val;
					exist = 1; break;
				}
				else if (link->next == NULL)
				{
					Tri tmp = new Atri;
					tmp->a[0] = a[0]; tmp->a[1] = a[1]; tmp->a[2] = a[2];
					tmp->val = val; tmp->next = NULL; link->next = tmp; break;
				}
				else if (link->next != NULL)
				{
					link = link->next;
				}
			}
		}
		else
		{
			Tri tmp = new Atri;
			tmp->a[0] = a[0]; tmp->a[1] = a[1]; tmp->a[2] = a[2];
			tmp->val = val; tmp->next = NULL; 
			tris[a[0]+a[1]+a[2]]->next= tmp;
		}
	}
	scanf("%d", &m);
	for (i = 0; i<m; i++)
	{
		scanf("%d%d%d", &a[0], &a[1], &a[2]);
		sort(a, a + 3);
		gcdof = gcd(a[0], gcd(a[1], a[2]));
		printf("%d\n",gcdof); 
		a[0] /= gcdof; a[1] /= gcdof; a[2] /= gcdof;
		Tri link = tris[a[0]+a[1]+a[2]]->next;                        //link代表这个key值的链表头指针 
		if (link != NULL)
		{
			while (1)
			{
				if (link->a[0] == a[0] && link->a[1] == a[1] && link->a[2] == a[2])
				{
					printf("%d\n", link->val);
					break;
				}
				else if (link->next == NULL)
				{
					printf("Sorry\n"); break;
				}
				else if (link->next != NULL)
				{
					link = link->next;
				}
			}
		}
		else printf("Sorry\n");
	}
	return 0;
}

PS:第二次实现三角形,对链表使用熟悉多了,三角形已经AC了,代码已更新;

posted @ 2017-12-04 22:02  heihuifei  阅读(1127)  评论(0编辑  收藏  举报