๊ณจ๋“œ1 : ๊ธฐํ•˜ ๋ฌธ์ œ์ด๋‹ค.

์ƒ๊ฐ

๋ณผ๋ก ๊ป์งˆ, Convex Hull์ด๋ผ ํ•œ๋‹ค. ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ ์œ ๋ช…ํ•œ ๊ฒƒ์„ ๊ทธ๋ผํ•จ ์Šค์บ” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ธ๋ฐ, ํ•ด๋‹น ๋™์˜์ƒ์„ ๋ด๋ณด์ž.

์ด๊ฒƒ๊ณผ ๊ฐ™์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค.

  1. ๊ฐ€์žฅ y๊ฐ€ ์ž‘์€ ์ ์„ ๊ตฌํ•œ๋‹ค.
  2. ๊ทธ ์ ์„ ๊ธฐ์ค€์œผ๋กœ ์ง์„ ์˜ ๊ฐ์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ๋‹ค.
  3. ๊ฐ์ด ๊ฐ€์žฅ ์ž‘์€ ์ ๋ถ€ํ„ฐ ์กฐ์‚ฌํ•˜๋ฉด์„œ ๋ณผ๋ก ๊ป์งˆ์ธ์ง€ ์•„๋‹Œ์ง€ ํ™•์ธํ•˜๊ณ  ์ถ”๊ฐ€ํ•œ๋‹ค.

์ด ๋•Œ, ๊ฐ์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๊ฐ์€ double ํ˜•์ด๋ผ ์ด๋ฅผ ์ •๋ ฌํ•˜๋Š”๋ฐ ์ข‹์ง€ ์•Š๋‹ค. ์ผ๋‹จ ๊ตฌํ•˜๊ธฐ๋„ ์–ด๋ ต๊ณ  ๊ฐ™์€ ์„ ์ƒ์— ์žˆ์„ ๋•Œ ๊ณจ์น˜๊ฐ€ ์•„ํ”„๋‹ค..

๊ทธ๋ž˜์„œ ์ด ๋•Œ ๊ฐ์„ ๋Œ€๋ณ€ํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ์ง€ํ‘œ๋กœ ์™ธ์ ์˜ ๋ถ€ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ๋ถ€๋ถ„์ด ๋‹ฌ๋‹ฌํ•œ ๋ถ€๋ถ„์ธ๋ฐ, ์™ธ์ ์˜ ๊ฐ’์€ x, y์ถ•์„ ๊ธฐ์ €๋กœ ๋ณด์•˜์„ ๋•Œ, ์‹œ๊ณ„ ๋ฐฉํ–ฅ, ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์„ ๋Œ€๋ณ€ํ•ด ์ค€๋‹ค. ์ด ๋•Œ, ํŠน์ • ๋‘ ์ ๊ณผ์˜ ์™ธ์ ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ์„œ๋กœ์˜ ์ƒ๋Œ€์  ์œ„์น˜๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ด ์—ฐ์‚ฐ์„ ์ ๋“ค์„ ๊ฐ ์ˆœ์„œ๋กœ ์ •๋ ฌํ•˜๋Š” ๋น„๊ต ์—ฐ์‚ฐ์œผ๋กœ ์‚ฌ์šฉํ•˜์ž.

Code

#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
struct Point{
    ll x, y;
};
vector<Point> p;
int N;
 
ll ccw(Point p1, Point p2, Point p3){
    return p1.x*p2.y + p2.x*p3.y + p3.x*p1.y - (p2.x*p1.y + p3.x*p2.y + p1.x*p3.y);
}
 
bool compareMinelement(Point p1, Point p2){
    if (p1.y == p2.y) return p1.x < p2.x;
    else return p1.y < p2.y;
}
 
bool compareCCW(Point p1, Point p2){
    ll cp = ccw(p[0], p1, p2);
    if (cp == 0) return (p1.x + p1.y) < (p2.x + p2.y);
    return cp > 0;
}
 
 
 
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> N;
    p.resize(N);
 
    for (int i = 0; i < N; i++) {
        cin >> p[i].x >> p[i].y;
    }
 
    sort(p.begin(), p.end(), compareMinelement);
    sort(p.begin()+1, p.end(), compareCCW);
 
    vector<Point> v;
    v.push_back(p[0]);
    v.push_back(p[1]);
 
    // ์ด for๋ฌธ์€ ์„ธ์  ์ค‘ ๊ฐ€์žฅ ๋ฐ”๊นฅ์ชฝ ์ ์„ ์˜๋ฏธ
    for (int i = 2; i < N; i++) {
        // ๋ณผ๋ก์„ ์ฐพ์„ ๋•Œ๊นŒ์ง€ ๊ณ„์† ์ง„ํ–‰
        while (v.size() >= 2) {
            // ๋‘๊ฐœ๋ฅผ ๋ณธ๋‹ค.
            Point p2 = v.back();
            v.pop_back();
            Point p1 = v.back();
            // ccw์ด๋ฉด ์ค‘๊ฐ„์— ์žˆ๋Š” ์ (p2)๋ฅผ ํ™•์ธ๋œ ์ ์œผ๋กœ ํŒ๋‹จํ•˜๊ณ  ์Šคํƒ์— ๋„ฃ๋Š”๋‹ค.
            if (ccw(p1, p2, p[i]) > 0) {
                v.push_back(p2);
                break;
            }
            // ccw๊ฐ€ ์•„๋‹ˆ๋ฉด p2๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ๋ง๊ณ  p2์ด์ „์˜ 2์ ๊ณผ ํ˜„์žฌ p[i]์™€ ccw์ธ์ง€ ๋น„๊ตํ•œ๋‹ค. (์ฒ˜์Œ์œผ๋กœ ๋Œ์•„๊ฐ„๋‹ค)
        }
        // while๋ฌธ์„ ํ†ต๊ณผํ–ˆ๋‹ค๋ฉด ์ ์ด ์ถ”๊ฐ€๊ฐ€ ๋œ ๊ฒƒ์ด๋ฏ€๋กœ ํ˜„์žฌ ํƒ์ƒ‰ํ•˜๋Š” ๊ฐ€์žฅ ๋ฐ”๊นฅ์ชฝ ์ ๋„ ๋„ฃ์–ด์ค€๋‹ค.
        v.push_back(p[i]);
    }
    cout << v.size() <<  '\n';
}

๋ณด๋‹ค ๊น”๋”ํ•œ Convex Hull Code

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
struct Point {
   ll x, y;
   Point(ll a, ll b) :x(a), y(b) {};
   Point() {};
   bool operator<(const Point &rhs) const {
      if (x != rhs.x) return x < rhs.x;
      return y < rhs.y;
   }
};
vector<Point> point;
 
ll ccw(Point pt1, Point pt2, Point pt3) {
   ll ret = pt1.x*pt2.y + pt2.x*pt3.y + pt3.x*pt1.y;
   ret -= (pt2.x*pt1.y + pt3.x*pt2.y + pt1.x*pt3.y);
   return ret;
}
ll dist(Point pt1, Point pt2) {
   ll dx = pt2.x - pt1.x;
   ll dy = pt2.y - pt1.y;
   return dx * dx + dy * dy;
}
 
int main(){
    int N;
    cin >> N;
    point.resize(N);
    for (int i = 0; i < N; i++) {
        cin >> point[i].x >> point[i].y;
    }
    vector<Point> hull;
    swap(point[0], *min_element(point.begin(), point.end()));
    sort(point.begin() + 1, point.end(), [](Point x, Point y) {
       ll cw = ccw(point[0], x, y);
       if (cw == 0) return dist(point[0], x) < dist(point[0], y);
       return cw > 0;
    });
 
    for (auto i : point) {
        // hull์˜ ๋’ค์—์„œ 2๋ฒˆ์งธ ๊ฐ’, 1๋ฒˆ์งธ ๊ฐ’, ๊ทธ๋ฆฌ๊ณ  point์˜ 3๋ฒˆ์งธ ๊ฐ’์„ ๋น„๊ตํ•˜์—ฌ
        // ๋ฐ˜์‹œ๊ณ„๊ฐ€ ์•„๋‹ˆ๋ฉด hull์˜ ๋งจ ๋’ค์˜ ์ ์„ ๋บ€๋‹ค.
        // ๋ฐ˜์‹œ๊ณ„์ด๋ฉด ํ•ด๋‹น ์ ์„ ํฌํ•จํ•œ ์ƒํƒœ๋กœ ๋‹ค์Œ์ ์„ ๋น„๊ตํ•œ๋‹ค.
       while (hull.size() >= 2 && ccw(hull[hull.size() - 2], hull.back(), i) <= 0) {
          hull.pop_back();
       }
       hull.push_back(i);
    }
    cout << hull.size() << endl;
}

Reference