文章目录
- 计算几何基础
- 平面几何距离
- 圆的周长和面积
- 圆与圆之间的关系:
- 海伦公式计算三角形面积
- 点到直线的距离
- 点积和叉积
- 例题:
- 点和线的关系
- 点的表示形式和代码
- 判断点在直线的那边
- 点到线的垂足
- 点到线的距离
- 例题-1242
- 例题-1240
- 升级--点到线段的距离--1285
- 任意多边形面积的计算
- 平面向量
- 向量积
- 求任意多边形的面积:
- 二维计算几何基础
计算几何基础
平面几何距离
- 曼哈顿距离:
int dist(int x1,int y1,int x2,int y2)
{int dx=abs(x1-x2);int dy=abs(y1-y2);return dx+dy;
}
- 欧几里得距离:
double dist(double x1,double y1,double x2,double y2)
{double dx=x1-x2;double dy=y1-y2;return sqrt(dx*dx+dy*dy);
}
其中,pow函数是比较慢的,这里没有必要使用。
圆的周长和面积
圆与圆之间的关系:
海伦公式计算三角形面积
点到直线的距离
- 那么向量如何求解这个问题:
- 例题:1286
#include<bits/stdc++.h>
using namespace std;
//求距离
double dist(double x1,double y1,double x2,double y2)
{double dx=x1-x2,dy=y1-y2;return sqrt(dx*dx+dy*dy);}
void solve()
{double xa,ya,xb,yb,xc,yc;cin>>xa>>ya>>xb>>yb>>xc>>yc;//把向量处理出来,ca,cbdouble xca=xa-xc,yca=ya-yc;double xcb=xb-xc,ycb=yb-yc;//叉乘 double ans=abs(xca*ycb-xcb*yca)/dist(xa,ya,xb,yb);cout<<fixed<<setprecision(2)<<ans<<endl;
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int i;cin>>i;while(i--)solve();return 0;
}
- 总结:
- 封装函数,按照输入的组别来处理。
- 在这个函数中处理出两条边叉乘的结果。
- 最终的结果是叉乘结果的绝对值除以两者之间的距离。
- 求距离再次封装一个函数:使用欧几里得算法。
- 注意使用double类型以及保留小数位数。
- 例题:求三角形面积–1231
#include<bits/stdc++.h>
using namespace std;
using ll =long long;
//求距离
double dist(double x1,double y1,double x2,double y2)
{double dx=x1-x2,dy=y1-y2;return sqrt(dx*dx+dy*dy);}
void solve()
{double x1,y1,x2,y2,x3,y3;cin>>x1>>y1>>x2>>y2>>x3>>y3;long double a=dist(x1,y1,x2,y2);long double b=dist(x1,y1,x3,y3);long double c=dist(x2,y2,x3,y3);//开了一次根号,再求一次根号很容易导致精度误差 long double p=(a+b+c)/2;long double ans=sqrt(p*(p-a)*(p-b)*(p-c));cout<<fixed<<setprecision(2)<<ans<<endl;
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int i;cin>>i;while(i--)solve();return 0;
}
点积和叉积
- 概念:
- 点积的代码实现:
#include<bits/stdc++.h>
using namespace std;struct Point{//定义点的结构体 double x,y;Point(){}Point(double x,double y):x(x),y(y){}Point operator+(Point p){return Point(x+p.x,y+p.y);}Point operator-(Point p){return Point(x-p.x,y-p.y);}Point operator*(double a){return Point(x*a,y*a);}Point operator/(double a){return Point(x/a,y/a);}Point operator*(Point p){return Point(x*p.x+y*p.y);}//点积 };
typedef Point Vector;
int main()
{Vector a(1.0,3.0);Vector b(2.0,4.0);double dot_product=a*b;//使用重载的*运算符计算点积cout<<dot_product<<endl;return 0; }
- 叉积
- 代码实现:
#include<bits/stdc++.h>
using namespace std;struct Point{//定义点的结构体 double x,y;Point(){}Point(double x,double y):x(x),y(y){}
//乘法 Point operator*(double a){return Point(x*a,y*a);}
//点乘 Point operator*(Point p){return Point(x*p.x+y*p.y);}//点积 double cross(const Point &p)const{return x*p.y-y*p.x;} };
typedef Point Vector;
int main()
{Vector a(1.0,3.0);Vector b(2.0,4.0);double dot_product=a*b;//使用重载的*运算符计算点积cout<<dot_product<<endl;double cross_product=a.cross(b);cout<<cross_product<<endl;return 0; }
例题:
- 怎么判断两条边是否垂直呢?
点积为0即可。
#include<bits/stdc++.h>
using namespace std;struct Point{//定义点的结构体 double x,y;Point():x(0),y(0) {} //初始化 //两点相减,得到向量double operator-(const Point &p)const{return x-p.x,y-p.y};Point(double x,double y):x(x),y(y){}
//点积double dot(const Point &p)const{return x*p.x-y*p.y;}
// 判断当前的向量和另一向量是否垂直bool ischui(const Point &p)const{return fabs(dot(p))<1e-10;//点积为0即垂直 }
}; int main()
{int n,k,count=0;cin>>n>>k;for(int i=0;i<n;i++){Point start,turn,end;cin>>start.x>>start.y;cin>>turn.x>>turn.y;cin>>end.x>>end.y;
// 计算两个向量Point v1=turn-start;Point v2=end-turn;
// 检查是否垂直if(ischui(v2)){count++;}
// 计算上取整int result=(count+k-1)/k;cout<<result<<end;return 0; } }
点和线的关系
点的表示形式和代码
//使用pair存储
using Point =pair<int,int>;
//使用结构体
struct Point{int x,y;
};
判断点在直线的那边
点到线的垂足
点到线的距离
例题-1242
#include<bits/stdc++.h>
using namespace std;
struct Point{double x;double y;
};
inline double cross(const Point& p1,const Point& p2)
{return p1.x*p2.y-p2.x*p1.y;
}
int main()
{int n;Point p1,p2,p3;cin>>n;while(n--){cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y;cout<<(cross(p1,p2)+cross(p2,p3)+cross(p1,p3)==0?"Yes":"No")<<endl;}return 0;
}
inline表示建议编译器将cross函数的实现直接插入到调用它的地方,以提高性能。
例题-1240
#include <bits/stdc++.h>
using namespace std;void solve(){double xa,ya,xb,yb,xc,yc;cin>>xa>>ya>>xb>>yb>>xc>>yc;double xAB=xb-xa,yAB=yb-ya;double xBC=xb-xc,yBC=yb-yc;double p=xAB*yBC-xBC*yAB;if(p==0){cout<<"IN"<<"\n";}else if(p>0){cout<<"R"<<"\n";}else{cout<<"L"<<"\n";}
}int main()
{int t;cin>>t;while(t--)solve();return 0;
}
总结:遇到直线用向量比较好。
升级–点到线段的距离–1285
?:这时候还能不能做垂线呢?
能。且点到直线的距离有一个垂足,判断垂足是否在线段AB内。
#include <bits/stdc++.h>
using namespace std;double dist(double x1,double y1,double x2,double y2){double dx=x1-x2,dy=y1-y2;return sqrt(dx*dx+dy*dy);
}int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int t;cin>>t;while(t--){double xa,ya,xb,yb,xc,yc;cin>>xa>>ya>>xb>>yb>>xc>>yc;if((yb-ya)/(xb-xa)!=(yc-yb)/(xc-xb)){double xCA=xa-xc,yCA=ya-yc;double xCB=xb-xc,yCB=yb-yc;double ans=abs(xCA*yCB-xCB*yCA)/dist(xa,ya,xb,yb);cout<<fixed<<setprecision(2)<<ans<<"\n";}else{double d1=dist(xa,ya,xc,yc);double d2=dist(xb,yb,xc,yc);cout<<fixed<<setprecision(2)<<min(d1,d2)<<"\n";}}return 0;
}
- 题解逻辑;
- 当斜率不相等时,利用点到直线的距离公式求距离。
- 当斜率相等时,也就是说c在直线AB上,求ca和cb的最小值。
任意多边形面积的计算
平面向量
向量积
- 内积:
- 外积:
求任意多边形的面积:
- 求三角形的面积
#include<bits/stdc++.h>
using namespace std;
using ll =long long;
//求距离
double dist(double x1,double y1,double x2,double y2)
{double dx=x1-x2,dy=y1-y2;return sqrt(dx*dx+dy*dy);}
void solve()
{double x1,y1,x2,y2,x3,y3;cin>>x1>>y1>>x2>>y2>>x3>>y3;long double a=dist(x1,y1,x2,y2);long double b=dist(x1,y1,x3,y3);long double c=dist(x2,y2,x3,y3);//开了一次根号,再求一次根号很容易导致精度误差 long double p=(a+b+c)/2;long double ans=sqrt(p*(p-a)*(p-b)*(p-c));cout<<fixed<<setprecision(2)<<ans<<endl;
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int i;cin>>i;while(i--)solve();return 0;
}
二维计算几何基础
参考文献