๊ณจ๋1 : ๊ธฐํ ๋ฌธ์ ์ด๋ค.
์๊ฐ
๋ณผ๋ก ๊ป์ง, Convex Hull์ด๋ผ ํ๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์์ ์ ๋ช ํ ๊ฒ์ ๊ทธ๋ผํจ ์ค์บ ์๊ณ ๋ฆฌ์ฆ์ธ๋ฐ, ํด๋น ๋์์์ ๋ด๋ณด์.
์ด๊ฒ๊ณผ ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ์ ์ฐจ๋ฅผ ๊ฑฐ์ณ์ผ ํ๋ค.
- ๊ฐ์ฅ y๊ฐ ์์ ์ ์ ๊ตฌํ๋ค.
- ๊ทธ ์ ์ ๊ธฐ์ค์ผ๋ก ์ง์ ์ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ๋ค.
- ๊ฐ์ด ๊ฐ์ฅ ์์ ์ ๋ถํฐ ์กฐ์ฌํ๋ฉด์ ๋ณผ๋ก ๊ป์ง์ธ์ง ์๋์ง ํ์ธํ๊ณ ์ถ๊ฐํ๋ค.
์ด ๋, ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌ์ ์ํํด์ผ ํ๋๋ฐ, ๊ฐ์ 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;
}