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

 

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

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

 

6646번: Wooden Fence

Did you ever wonder what happens to your money when you deposit them to a bank account? All banks hold such deposits in various assets, such as gold, stocks, obligations, deposits in other banks, loans, bonds, and many others. Due to the financial crisis a

www.acmicpc.net

 

벨 나무들을 먼저 결정한다면, 남은 나무를 감싸는 울타리의 최소 길이는 남은 나무들로 이루어진 Convex Hull의 둘레의 길이와 같음을 관찰하자.

이 둘레의 길이가 베어진 나무로 만들 수 있는 울타리의 길이보다 작거나 같은 모든 경우를 찾아 각 경우의 베어진 나무의 가치의 합을 계산하고, 그 중 최솟값을 찾아 문제를 해결하자. 전체 나무 수\(N\)의 값이 16 이하로 매우 작으므로 모든 경우를 조사해도 충분히 문제를 해결할 수 있다.

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

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

struct point {
	int x, y, v, l;
	point() {};
	bool operator< (point &p) {
		if (x != p.x) return x < p.x;
		return y < p.y;
	}
};

int CCW(point &p1, point &p2, point &p3) {
	return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p1.x * p3.y - p2.x * p1.y - p3.x * p2.y;
}

int N, NN;
point P[16];
int ans = 1000000007;
vector<point> uhull, lhull;

void buildhull(int cN) {
	uhull.clear();
	for (int i = 0, b = 1; i < N; i++, b <<= 1) {
		if (cN & b) continue;
		while (uhull.size() > 1) {
			if (CCW(uhull[uhull.size() - 2], uhull.back(), P[i]) < 0) break;
			uhull.pop_back();
		}
		uhull.emplace_back(P[i]);
	}
	lhull.clear();
	for (int i = 0, b = 1; i < N; i++, b <<= 1) {
		if (cN & b) continue;
		while (lhull.size() > 1) {
			if (CCW(lhull[lhull.size() - 2], lhull.back(), P[i]) > 0) break;
			lhull.pop_back();
		}
		lhull.emplace_back(P[i]);
	}

	ld d = 0; int v = 0, l = 0, usize = uhull.size(), lsize = lhull.size();
	for (int i = 0; i + 1 < usize; i++) {
		d += hypotl(abs(uhull[i + 1].x - uhull[i].x), abs(uhull[i + 1].y - uhull[i].y));
	}
	for (int i = 0; i + 1 < lsize; i++) {
		d += hypotl(abs(lhull[i + 1].x - lhull[i].x), abs(lhull[i + 1].y - lhull[i].y));
	}
	for (int i = 0, b = 1; i < N; i++, b <<= 1) {
		if (!(cN & b)) continue;
		v += P[i].v, l += P[i].l;
	}
	if (d > l) return;
	ans = min(ans, v);
}

void solve() {
	NN = 1 << N;
	for (int i = 0; i < N; i++) cin >> P[i].x >> P[i].y >> P[i].v >> P[i].l;
	sort(P, P + N);
	ans = 1000000007;
	for (int i = 0; i + 1 < NN; i++) buildhull(i);
	cout << "The lost value is " << ans << ".\n";
}

int T;

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

	cin >> N;
	while (N) {
		solve();
		cin >> N;
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 12971 // C++] 숫자 놀이  (0) 2024.04.09
[BOJ 13728 // C++] 행렬식과 GCD  (0) 2024.04.08
[BOJ 7827 // C++] Transitive Closure  (0) 2024.04.06
[BOJ 14156 // C++] Binarni  (0) 2024.04.05
[BOJ 23090 // C++] 난민  (0) 2024.04.04

+ Recent posts