神坛 (30 分)(立体几何&求三个点组成的最小面积)

题目:https://pintia.cn/problem-sets/994805046380707840/problems/994805046577840128

在古老的迈瑞城,巍然屹立着 n 块神石。长老们商议,选取 3 块神石围成一个神坛。因为神坛的能量强度与它的面积成反比,因此神坛的面积越小越好。特殊地,如果有两块神石坐标相同,或者三块神石共线,神坛的面积为 0.000。
n是5000;
输出格式:
在一行中输出神坛的最小面积,四舍五入保留 3 位小数。

解决办法:
枚举每一个点当极坐标的原点,求其它点相对于这个i点的位置,也可以理解为向量,然后再按照叉积排序,最后相邻的俩个相邻就是最小的,遍历所有相邻的就ok。

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
//#include<bits/stdc++.h>
#define PII pair<int, int>
//#define x first
//#define y second
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 5000 + 7;
using namespace std;

struct Point {  //存点
    ll x, y;    //这里必须用ll,double在下面的运算中会爆掉
    Point() {}
    Point(ll x, ll y) : x(x), y(y){};
    Point operator+(Point A) { return Point(x + A.x, y + A.y); }
    Point operator-(Point A) { return Point(x - A.x, y - A.y); }
    bool operator<(const Point &A) const { return x * A.y - y * A.x > 0; }
} P[N], Q[N];   //P存点,Q用来存极坐标点(可以理解为向量)

ll Cross(Point A, Point B) { return A.x * B.y - A.y * B.x; }//求叉积
int main(int argc, char const *argv[]) {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%lld%lld", &P[i].x, &P[i].y);
    }
    double minn = INF;
    for (int i = 1; i <= n; i++) {
        int tol = 0;
        for (int j = 1; j <= n; j++) {  //把相对于i点的极坐标都求出来,即向量
            if (i != j) Q[++tol] = P[j] - P[i];
        }
        sort(Q + 1, Q + 1 + tol);  //按照叉积排序
        for (int j = 1; j < tol; j++) {
         //     if (Cross(Q[j], Q[j + 1])<0)printf("100\n");  //排完以后叉积没有小于0的了,放开交了一发也A了
            minn = min(minn, fabs(Cross(Q[j], Q[j + 1])) * 0.5);  //相邻俩个即最小
        }
         minn = min(minn,fabs(Cross(Q[1],Q[tol]))*0.5);  //这一条好像不加也能A
    }
    printf("%.3lf\n", minn);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值