题目看起来比较有趣,模拟人脸识别,指纹识别。具体是这样的:用两组点分别表示两个几何图形,判断这两个几何图形是否相似。“相似“的标准是:通过旋转和放大缩小操作能过使两个图形相等。
判断旋转要用到向量积和标量积,光用一个是不够的,因为 sin 和 cos 函数在 0 到 360 度定义域内的值不是唯一的。
判断放大缩小,只要算向量的模就可以。
#include<iostream>
#include<cmath>
#define EPS 1e-9
#define feq(a, b) (fabs((a)-(b)) < EPS)
using namespace std;
typedef struct{
double x, y;
} POINT;
POINT vect[2][20];
double dist(POINT a, POINT b){
return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}
double crossProduct(POINT a, POINT b){
POINT o = {0, 0};
return ((a.x * b.y) - (a.y * b.x)) / (dist(a, o) * dist(b, o));
}
double dotProduct(POINT a, POINT b){
POINT o = {0, 0};
return ((a.x * b.x) + (a.y * b.y)) / (dist(a, o) * dist(b, o));
}
void print(POINT a[], int n){
for(int i = 0; i < n; i++)
cout << a[i].x << " " << a[i].y << endl;
}
int main(){
int n;
while(cin >> n){
if(n == 0)
break;
for(int j = 0; j < 2; j++){ //input
POINT origin;
cin >> origin.x >> origin.y;
for(int i = 0 ; i < n - 1; i++){
POINT temp, temp2;
cin >> temp.x >> temp.y;
temp2 = temp;
temp.x -= origin.x;
temp.y -= origin.y;
vect[j][i] = temp;
origin = temp2;
}
}
bool eq = true;
double angle = crossProduct(vect[0][0], vect[1][0]); //判断旋转
double angle1 = dotProduct(vect[0][0], vect[1][0]);
for(int i = 1; i < n - 1; i++){
double temp = crossProduct(vect[0][i], vect[1][i]);
double temp1 = dotProduct(vect[0][i], vect[1][i]);
if(!feq(temp, angle) || !feq(temp1, angle1)){
eq = false;
break;
}
}
POINT o = {0, 0};
double ratio = dist(vect[0][0], o)/dist(vect[1][0], o); //判断伸缩
for(int i = 1; i < n - 1; i++){
double temp = dist(vect[0][i], o)/dist(vect[1][i], o);
if(!feq(temp, ratio)){
eq = false;
break;
}
}
if(eq)
cout << "similar" << endl;
else
cout << "dissimilar" << endl;
}
}