※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 13218번 문제인 Bitcoin이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/13218 

 

13218번: Bitcoin

Bitcoin mining is a very power consuming task. One day, both Ali and Betty wish to start their own mining fields (one field for each of them) in central of Cheras. Hence, Ali and Betty went to Siva, the Mayor of Cheras, to request for locations. Siva prese

www.acmicpc.net

주어지는 점들 중 가장 먼 두 점 사이의 거리를 묻는 문제이다. 이는 convex hull 위에서의 rotating calipers 테크닉을 이용해 해결할 수 있음이 잘 알려져있다. 이를 이용해 문제를 해결하자.

 

(글쓴이는 적용하지는 않았지만) 이에 더해 주어진 좌표의 범위가 충분히 작다는 점을 이용해 convex hull을 구성하는 꼭짓점의 후보를 추리는 것으로 속도 향상을 꾀할 수도 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef long double ld;

int N;
pll points[1000000];
vector<pll> upperhull; // leftmost x의 lowermost y부터 rightmost x의 uppermost y까지
vector<pll> lowerhull;

int CCW(pll& A, pll& B, pll& C) {
	ll ccw = (B.first - A.first) * (C.second - A.second) - (B.second - A.second) * (C.first - A.first);
	if (ccw > 0) return 1;
	else if (ccw < 0) return -1;
	else return 0;
}

void andrew_algorithm() {
	sort(points, points + N);

	//upperhull
	for (int i = 0; i < N; i++) {
		auto& cur = points[i];
		int cursize = upperhull.size();
		while (cursize > 1) {
			auto& L = upperhull[cursize - 2], & M = upperhull[cursize - 1];
			if (CCW(L, M, cur) != -1) upperhull.pop_back(), cursize--;
			else break;
		}
		upperhull.emplace_back(cur);
	}

	//lowerhull
	for (int i = 0; i < N; i++) {
		auto& cur = points[i];
		int cursize = lowerhull.size();
		while (cursize > 1) {
			auto& L = lowerhull[cursize - 2], & M = lowerhull[cursize - 1];
			if (CCW(L, M, cur) != 1) lowerhull.pop_back(), cursize--;
			else break;
		}
		lowerhull.emplace_back(cur);
	}
}

ll dfunc(pll& p1, pll& p2) {
	return (p1.first - p2.first) * (p1.first - p2.first) + (p1.second - p2.second) * (p1.second - p2.second);
}

void rotating_calipers() {
	int u = 0, uend = upperhull.size(), l = lowerhull.size() - 1;
	ll mx = dfunc(upperhull[u], lowerhull[l]);
	while (u < uend - 1 && l > 0) {
		if (upperhull[u].first == upperhull[u + 1].first) u++;
		else if (lowerhull[l].first == lowerhull[l - 1].first) l--;
		else {
			ll dx1 = upperhull[u + 1].first - upperhull[u].first, dy1 = upperhull[u + 1].second - upperhull[u].second;
			ll dx2 = lowerhull[l].first - lowerhull[l - 1].first, dy2 = lowerhull[l].second - lowerhull[l - 1].second;

			if (dy1 * dx2 > dx1 * dy2) u++;
			else l--;
		}
		mx = max(mx, dfunc(upperhull[u], lowerhull[l]));
	}

	while (u < uend - 1) {
		u++;
		mx = max(mx, dfunc(upperhull[u], lowerhull[l]));
	}
	while (l > 0) {
		l--;
		mx = max(mx, dfunc(upperhull[u], lowerhull[l]));
	}

	cout << mx;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> N;
	int trash; cin >> trash;
	for (int i = 0; i < N; i++) cin >> points[i].first >> points[i].second;

	andrew_algorithm();
	rotating_calipers();
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 13220 // C++] Secret  (0) 2023.05.29
[BOJ 13219 // C++] Trains  (0) 2023.05.28
[BOJ 13217 // C++] Honey  (0) 2023.05.26
[BOJ 13241 // C++] 최소공배수  (0) 2023.05.25
[BOJ 13245 // C++] Sum of digits  (0) 2023.05.24

+ Recent posts