POJ 1931

题意:生物面部特征识别,开始先输入特征数(坐标数),然后输入相应特征的坐标,输入两组(代表两张脸),判断这两张脸是否相似。


思路:建立链表筛选重点,并且删去多于的重点只留一个;然后用X乘的方法判断图形方向( 点与点之间的位置关系,是否能通过旋转、平移、放缩重合),再用点乘的方法判断钝角锐角(主要是区分0度与180度),最后用边比边的方法判定是否相似。


代码:
#include<iostream>
#include<cmath>
using namespace std;
struct coor
{
   double x;
   double y;
   coor *before;
   coor *next;
};
int main()
{
   int n;
   coor *head1,*head2,*p1,*p2;
   while(cin>>n,n)
   {
       head1=head2=NULL;
       for(int i=0;i<n;i++)
       {
           p1=new coor;
           cin>>p1->x>>p1->y;
           if(head1==NULL){head1=p1;p1->before=NULL;}
           else 
           {
               p2->next=p1;
               p1->before=p2;
           }
           p2=p1;
       }
       p1->next=NULL;
       for(int i=0;i<n;i++)
       {
           p1=new coor;
           cin>>p1->x>>p1->y;
           if(head2==NULL){head2=p1;p1->before=NULL;}
           else 
           {
               p2->next=p1;
               p1->before=p2;
           }
           p2=p1;
       }
       p1->next=NULL;
       int flag=0;
       for(coor *pp1=head1,*pp2=head2,*del1=NULL,*del2=NULL;pp1!=NULL&&pp2!=NULL;pp1=pp1->next,pp2=pp2->next)
       {
           for(p1=pp1->next,p2=pp2->next;p1!=NULL&&p2!=NULL;p1=p1->next,p2=p2->next)
           {
               if(del1!=NULL)
               {
                   delete del1;
                   delete del2;
                   del1=NULL;
                   del2=NULL;
               }
               if(pp1->x==p1->x&&pp1->y==p1->y)
               {
                   if(pp2->x==p2->x&&pp2->y==p2->y)
                   {
                       p1->before->next=p1->next;
                       p2->before->next=p2->next;
                       if(p1->next!=NULL)
                       {
                           p1->next->before=p1->before;
                           p2->next->before=p2->before;
                       }
                       del1=p1;
                       del2=p2;
                       continue;
                   }
                   else break;
               }
               else if(pp2->x==p2->x&&pp2->y==p2->y)break;
           }
           if(del1!=NULL)
           {
               delete del1;
               delete del2;
               del1=NULL;
               del2=NULL;
           }
           if(p1!=NULL){flag=1;break;}
       }
       if(flag==1)
       {
           cout<<"dissimilar"<<endl;
           for(p1=head1,p2=head2;p1!=NULL;)
           {
               coor *temp1,*temp2;
               temp1=p1;temp2=p2;
               p1=p1->next;p2=p2->next;
               delete temp1;
               delete temp2;
           }
           continue;
       }
       int n0=0;
       for(p1=head1;p1!=NULL;p1=p1->next)n0++;
       if(n0==1||n0==2)
       {
           cout<<"similar"<<endl;
           for(p1=head1,p2=head2;p1!=NULL;)
           {
               coor *temp1,*temp2;
               temp1=p1;temp2=p2;
               p1=p1->next;p2=p2->next;
               delete temp1;
               delete temp2;
           }
           continue;
       }
       double *ssign1=new double[n0],*ssign2=new double[n0],*csign1=new double[n0],*csign2=new double[n0];
       p1=head1->next;p2=head2->next;
       for(int i=0;p1->next!=NULL;i++,p1=p1->next,p2=p2->next)
       {
           ssign1[i]=(p1->before->x-p1->x)*(p1->next->y-p1->y)-(p1->next->x-p1->x)*(p1->before->y-p1->y);
           ssign2[i]=(p2->before->x-p2->x)*(p2->next->y-p2->y)-(p2->next->x-p2->x)*(p2->before->y-p2->y);
           csign1[i]=(p1->before->x-p1->x)*(p1->next->x-p1->x)+(p1->before->y-p1->y)*(p1->next->y-p1->y);
           csign2[i]=(p2->before->x-p2->x)*(p2->next->x-p2->x)+(p2->before->y-p2->y)*(p2->next->y-p2->y);
       }
       coor *q1=p1,*q2=p2;
       p1=head1;p2=head2;
       ssign1[n0-2]=(q1->before->x-q1->x)*(p1->y-q1->y)-(p1->x-q1->x)*(q1->before->y-q1->y);
       ssign2[n0-2]=(q2->before->x-q2->x)*(p2->y-q2->y)-(p2->x-q2->x)*(q2->before->y-q2->y);
       csign1[n0-2]=(q1->before->x-q1->x)*(p1->x-q1->x)+(q1->before->y-q1->y)*(p1->y-q1->y);
       csign2[n0-2]=(q2->before->x-q2->x)*(p2->x-q2->x)+(q2->before->y-q2->y)*(p2->y-q2->y);
       ssign1[n0-1]=(q1->x-p1->x)*(p1->next->y-p1->y)-(p1->next->x-p1->x)*(q1->y-p1->y);
       ssign2[n0-1]=(q2->x-p2->x)*(p2->next->y-p2->y)-(p2->next->x-p2->x)*(q2->y-p2->y);
       csign1[n0-1]=(q1->x-p1->x)*(p1->next->x-p1->x)+(q1->y-p1->y)*(p1->next->y-p1->y);
       csign2[n0-1]=(q2->x-p2->x)*(p2->next->x-p2->x)+(q2->y-p2->y)*(p2->next->y-p2->y);
       int count1=0,count2=0;
       for(int i=0;i<n0;i++)
       {
           if(ssign1[i]>0&&ssign2[i]>0||ssign1[i]<0&&ssign2[i]<0||ssign1[i]==0&&ssign2[i]==0)count1++;
           if(csign1[i]>0&&csign2[i]>0||csign1[i]<0&&csign2[i]<0||csign1[i]==0&&csign2[i]==0)count2++;
       }
       delete []ssign1;
       delete []ssign2;
       delete []csign1;
       delete []csign2;
       if(count1==n0&&count2==n0)
       {
           double *a1=new double[n0],*a2=new double[n0];
           p1=head1;p2=head2;
           for(int i=0;i<n0-1;i++,p1=p1->next,p2=p2->next)  //算边的时候不要用sqrt(),会损失精度,之前用了sqrt,一直找不到问题,坑了两天(⊙o⊙)…。。。。直接用平方比即可
           {
               a1[i]=pow(p1->next->x-p1->x,2)+pow(p1->next->y-p1->y,2);
               a2[i]=pow(p2->next->x-p2->x,2)+pow(p2->next->y-p2->y,2);
           }
           a1[n0-1]=pow(head1->x-p1->x,2)+pow(head1->y-p1->y,2);
           a2[n0-1]=pow(head2->x-p2->x,2)+pow(head2->y-p2->y,2);
           int count=0;
           for(int i=0;i<n0-1;i++)
               if(a1[i]/a2[i]==a1[i+1]/a2[i+1])count++;
           if(count==n0-1)cout<<"similar"<<endl;
           else cout<<"dissimilar"<<endl;
           delete []a1;
           delete []a2;
       }
       else cout<<"dissimilar"<<endl;
       for(p1=head1,p2=head2;p1!=NULL;)
       {
           coor *temp1,*temp2;
           temp1=p1;temp2=p2;
           p1=p1->next;p2=p2->next;
           delete temp1;
           delete temp2;
       }
   }
       return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值