先简单看一道几何的题目吧。
常见的空间几何公式:
1.俩点之间的距离sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
2.平面三角公式:p = (a+b+c)/2 S = sqrt(p*(p-a)*(p-b)*(p-c));
一、在做几何问题时,经常会遇到精度问题。
在浮点运算时会产生精度误差,为了控制精度,一般设置一个偏差值eps,eps要大于浮点运算结果的不确定量,一般取1e-8;
比较2个浮点数时,不能直接用==判断相等,可以选择用dcmp()函数来判断;
const double eps = 1e-8;
int dcmp(double x,double y){
if(fabs(x - y) < eps) return 0;
else return x<y?-1:1;
}
二、点积和叉积。
点积(Dot product)编程时计算点积,并不需要知道θ。因为如果已知 A=(Ax,Ay),B=(Bx,By)那么就有:A•B=AxBx+AyBy。
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}
叉积(Cross product)它的计算公式是:A×B=∣A∣∣B∣sinθ,其中θ 表示向量 A 旋转到向量 B 所经过的夹角。两个向量的叉积是一个带正负号的数值
double Cross(Vector A,Vector B){return A.x*B.y – A.y*B.x;}
点积应用:
1.判断A和B的夹角是钝角还是锐角。
2.求向量A的长度。
3.求向量A与B的夹角大小。
叉积应用:
1.判断A与B的方向关系。
- 若 A×B>0,B 在 A 的逆时针方向;
- 若 A×B<0,B 在 A 的顺时针方向;
- 若 A×B=0,B 与 A 共线,可能是同方向的,也可能是反方向的。
2.计算俩向量构成的平行四边形又向面积。
3.计算三点构成的三角形的面积。
4.向量旋转。
5.用叉积检查俩个向量是否平行或重合。
问题描述:
平面上有 N 条直线,其中第 i 条直线是 y=Aix+Bi。
请计算这些直线将平面分成了几个部分。
输入描述
第一行包含一个整数 NNN。
以下 N 行,每行包含两个整数 Ai,Bi
其中,1≤N≤1000,−105≤Ai,Bi≤1051
输出描述
输出一个整数
思路:
我们可以先看第一条线和第二条线。第一条线可以把平面分成2半,第二条线如果与第一条线平行,则平面分成3个部分;如果不平行,有1个交点,则平面分成4个部分。
总结就是,每增加一条线,平面分割的增加数量 = 与先前直线的交点数 + 1;
#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
double A[N], B[N];
int main(){
int n; cin>>n;
pair<double, double> p;
set<pair<double, double>> s; //利用set自动去重功能筛选掉重边
for(int i = 0; i < n; i++){
cin >> p.first >> p.second ;
s.insert(p);
}
int i = 0; //将去重后的直线数据放回A,B数组
set<pair<double, double> >::iterator it = s.begin();
while(it != s.end()){
A[i] = it -> first;
B[i] = it -> second;
it++, i++;
}
long long ans = 2; //初始情况当只有一条直线时,有两个平面
for(int i = 1; i < s.size(); i++){ //从下标1开始,也就是第二条直线
set<pair< double, double> > pos; //记录第i条直线与先前的交点
for(int j = 0; j <= i-1; j++){
double a1 = A[i], b1 = B[i];
double a2 = A[j], b2 = B[j];
if(a1 == a2) continue; //平行线无交点,跳出
p.first = (b2-b1)/(a1-a2); //交点的x坐标
p.second = a1*(b2-b1)/(a1-a2) + b1; //交点的y坐标
pos.insert(p);
}
ans += pos.size() + 1; //与先前直线的交点数+1
}
printf("%d\n", ans);
return 0;
}
题目描述
平面直角坐标系中有一个三角形, 请你求出它的面积。
输入描述
第一行输入一个T ,代表测试数据量
每组测试数据输入有三行,每行一个实数坐标 (x,y) 代表三角形三个顶点。
输出描述
输出一个实数表示三角形面积。结果保留2位小数,误差不超过 10−210^{-2}10−2
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
double x1,y1,x2,y2,x3,y3;
cin>>x1>>y1>>x2>>y2>>x3>>y3;
double ans = (x2 - x1) * (y3 - y1) - (y2 - y1)*(x3 - x1);
printf("%.2f\n",ans*0.5);
}
return 0;
}
平面直角坐标系中有一个点 C 和一条直线 AB ,求点 C 和直线 AB 的位置关系。
输入描述
第一行输入一个 T ,代表测试数据量
每组测试数据输入有三行,每行一个实数坐标 (x,y) 分别代表 A,B,C 三个点。
输出描述
如果点 C 在直线 AB 上, 输出
IN
, 如果点 C 在直线 AB 左侧,输出L
, 如果点 C 在直线 AB 右侧输出R
。
代码:
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
double x,y,x2,y2,x3,y3;
int sgn(double x) {
if(fabs(x) < eps) return 0;
else return x<0 ? -1 : 1;
}
int check(){
int a = sgn((x3-x)*(y2-y) - (y3 - y)*(x2 - x));
if(a<0) return 1;
if(a>0) return -1;
return 0;
}
int main() {
int t;
cin>>t;
while(t--) {
cin>>x>>y>>x2>>y2>>x3>>y3;
if(check() == 0) cout<<"IN"<<endl;
else if(check() == 1) cout<<"L"<<endl;
else cout<<"R"<<endl;
}
return 0;
}