三角形(哈希函数)

实验任务

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

★数据输入

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

★数据输出

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

1093650-20171204215318972-229559746.png

1093650-20171204215348628-1770862895.png

解题思路:对于三角形三条边用哈希函数首先就是要找到一个函数找到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了,代码已更新;

转载于:https://www.cnblogs.com/heihuifei/p/7979231.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值