题意:生物面部特征识别,开始先输入特征数(坐标数),然后输入相应特征的坐标,输入两组(代表两张脸),判断这两张脸是否相似。
思路:建立链表筛选重点,并且删去多于的重点只留一个;然后用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;
}
#include<cmath>
using
struct
{
};
int
{
}