题意:
平面坐标系中一些点,找四个拼成面积在最小的矩形。
思路:
长方形判定定理:对角线相等,且互相平分的四边形是矩形。
首先平方枚举两个点所构成的所有线段。
对于这些线段把它们当做长方形的一条对角线,确定了这条对角线之后。
枚举第三个点,首先判断第三个点到对角线中点的距离是不是满足对角线长度的一半,(比较距离)
然后判断,与这三个点构成矩形的第四个点是不是存在:讲解一
如果以上两个判断都成立,那么算该长方形的面积(四个点都有了,算出长宽之积就ok)
然后用一个全局变量存满足条件的矩形的最小值就好。
讲解一:
如果判断第四个点存不存在呢?假设p1,p2,p3是已知的三个点。p1,p2构成对角线,对角线的中点是(a,b)
那么第四个点的坐标为:p3.x + (p3.x - a),p3.y + (p3.y - b).其中p3.x-a是p3到中点X轴方向的L1距离,仔细体会一下~
然后用一个map存一下所有的点就可以判断这个点在不在集合内了。
代码:
#define P pair<double,double>
class Solution {
public:
double esp = 1e-7;
double clac_len(vector<double>p1,vector<double>p2){ //计算两点之间距离
double aa = pow(p1[0]-p2[0],2)+pow(p1[1]-p2[1],2);
return sqrt(aa);
}
vector<double> to_vector(vector<vector<int>>& points,int num){
vector<double>tmp;
tmp.push_back(points[num][0]);tmp.push_back(points[num][1]);
return tmp;
}
double minAreaFreeRect(vector<vector<int>>& points) {
int sz = points.size();
double ans = 1e15;
map<P,int>ma;
for(int i=0;i<sz;i++){
ma[P(double(points[i][0]),double(points[i][1]))] = 1;
}
for(int i=0;i<sz;i++){
for(int j=0;j<sz;j++){
if(j==i)continue;
double halfx = (points[i][0]+points[j][0])*1.0/2; //中点
double halfy = (points[i][1]+points[j][1])*1.0/2;
vector<double>half;half.push_back(halfx);half.push_back(halfy);
for(int a=0;a<sz;a++){
if(a==j||a==i)continue;
vector<double>tmp1 = to_vector(points,i),tmp2 = to_vector(points,a);
if(fabs(clac_len(half,tmp1)-clac_len(half,tmp2))<esp){ //判断第三个点到中点的距离是不是对角线的一半
double x = 2*half[0] - points[a][0],y = 2*half[1]-points[a][1]; //计算第四个点
if(ma[P(x,y)]==1){
vector<double>tmp1 = to_vector(points,i),tmp2 = to_vector(points,a),tmp3 = to_vector(points,j);
double chang = clac_len(tmp1,tmp2);
double kuan = clac_len(tmp2,tmp3);
ans = min(ans,chang*kuan);
}
}
}
}
}
if(ans==1e15)ans = 0;
return ans;
}
};
此外还有一种平方log的做法.