POJ 1931

来源:互联网 发布:程序员能做到多少岁 编辑:程序博客网 时间:2024/06/05 23:46
题意:生物面部特征识别,开始先输入特征数(坐标数),然后输入相应特征的坐标,输入两组(代表两张脸),判断这两张脸是否相似。


思路:建立链表筛选重点,并且删去多于的重点只留一个;然后用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;
}
原创粉丝点击