BOJ/Platinum ~ Diamond

[BOJ/Platinum 5] 백준 6850 Cows(C++)

보단잉 2023. 4. 3. 18:38

문제 링크

 

문제

Your friend to the south is interested in building fences and turning plowshares into swords. In order to help with his overseas adventure, they are forced to save money on buying fence posts by using trees as fence posts wherever possible. Given the locations of some trees, you are to help farmers try to create the largest pasture that is possible. Not all the trees will need to be used.

However, because you will oversee the construction of the pasture yourself, all the farmers want to know is how many cows they can put in the pasture. It is well known that a cow needs at least 50 square metres of pasture to survive.

입력

The first line of input contains a single integer, n (1 ≤ n ≤ 10000), containing the number of trees that grow on the available land. The next n lines contain the integer coordinates of each tree given as two integers x and y separated by one space (where −1000 ≤ x, y ≤ 1000). The integer coordinates correlate exactly to distance in metres (e.g., the distance between coordinate (10, 11) and (11, 11) is one metre).

출력

You are to output a single integer value, the number of cows that can survive on the largest field you can construct using the available trees.

예제 입력 1

4
0 0
0 101
75 0
75 101

예제 출력 1

151

알고리즘 분류

  • 다각형의 넓이
  • 그레이엄 스캔

풀이

그레이엄 스캔을 통해 가장 큰 목초지를 만든다. 목초지는 볼록다각형이므로 삼각형 N-2개로 쪼개서 넓이를 구해야 한다.

넓이를 구했다면 50으로 나누어 생존 가능한 소의 마릿수를 출력한다.

코드

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#define INF 2e9
#define LL long long
#define FASTIO cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);

using namespace std;
struct POINT {
    int X, Y;
};

int N, X, Y, MinX, MinY, First;
vector<POINT> Point, CV;
double Area_Sum = 0;
int Answer;

void init() {
    MinX = INF;
    MinY = INF;
}

LL CCW(POINT A, POINT B, POINT C) {
    LL OP = ((A.X * B.Y) + (B.X * C.Y) + (C.X * A.Y));
    OP -= ((A.Y * B.X) + (B.Y * C.X) + (C.Y * A.X));
    return OP;
}

bool Comp(POINT A, POINT B) {
    LL NowCCW = CCW(Point[0], A, B);
    if (NowCCW != 0) {
        return (NowCCW > 0);
    }
    if (A.X != B.X) {
        return (A.X < B.X);
    }
    return (A.Y < B.Y);
}

void input() {
    cin >> N;
    for (int i = 0; i < N; i++) {
        cin >> X >> Y;
        POINT Tmp;
        Tmp.X = X;
        Tmp.Y = Y;
        Point.push_back(Tmp);
    }
}

void graham_Scan() {
    for (int i = 0; i < Point.size(); i++) {
        if ((MinX > Point[i].X) || ((MinX == Point[i].X) && (MinY > Point[i].Y))) {
            MinX = Point[i].X;
            MinY = Point[i].Y;
            First = i;
        }
    }
    swap(Point[0], Point[First]);
    sort(Point.begin() + 1, Point.end(), Comp);
    for (int i = 0; i < Point.size(); i++) {
        while ((CV.size() >= 2) && (CCW(CV[CV.size() - 2], CV[CV.size() - 1], Point[i]) <= 0)) {
            CV.pop_back();
        };
        CV.push_back(Point[i]);
    }
}

void settings() {
    graham_Scan();
}

void find_Answer() {
    for (int i = 1; i < (CV.size() - 1); i++) {
        LL Area = CCW(CV[0], CV[i], CV[i + 1]);
        double Half = Area / (double)2;
        Area_Sum += Half;
    }
    Answer = Area_Sum / 50;
    cout << Answer << "\n";
}

int main() {
    FASTIO
    init();
    input();
    settings();
    find_Answer();

    return 0;
}