POJ 1931 Biometrics (计算几何、标量积、向量积)

本文介绍了一种用于判断两个几何图形是否相似的算法。通过计算向量积和标量积来确定旋转角度,并通过计算向量模长来判断是否需要进行放大或缩小。该算法可用于人脸识别或指纹识别等场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目看起来比较有趣,模拟人脸识别,指纹识别。具体是这样的:用两组点分别表示两个几何图形,判断这两个几何图形是否相似。“相似“的标准是:通过旋转和放大缩小操作能过使两个图形相等。

判断旋转要用到向量积和标量积,光用一个是不够的,因为 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;

	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值