컴퓨터 사이언스/1고리즘

백준 1814 : 지붕 색칠하기

저세상 개발자 2021. 9. 4. 00:43

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

 

1814번: 지붕 색칠하기

첫째 줄에, 마을 내의 집들의 수 N이 주어진다. (1<=N<=10,000) 이후 N-1개의 줄에, 집들을 잇는 길의 정보가 하나씩 주어진다. 각 줄은 1이상 N이하 범위에 있는, 서로 다른 두 자연수 A, B로 구성되는데

www.acmicpc.net

 

tree dp문제다.

평소에 풀던 tree dp문제는 노드를 칠하거나 칠하지 않거나와 같은 두개의 상태값만 가졌다면, 이 문제는 두 개 이상의 상태값을 가질 수 있는 문제다.

 

이 문제에서 페인트 색깔은 최대 1만개까지 주어지는데 모든 색깔을 다 확인하면 시간초과가 발생하기 때문에 코스트가 낮은 색깔을 적절한 개수만큼 사용하여 문제를 해결해야 한다.

 

색깔은 logN개 만큼 확인해야하는데 그 근거는 아래 링크를 확인 바란다.

https://blog.encrypted.gg/144

 

[BOJ] 1693번: 트리 색칠하기

https://www.acmicpc.net/problem/1693 4색 문제에 의해 임의의 평면그래프는 4개의 색으로 인접한 node끼리 색이 겹치지 않게 만들 수 있고, 특히 트리의 경우 단 2가지 색으로 색이 겹치지 않게 할 수 있습

blog.encrypted.gg

 

#include <iostream>
#include <vector>
#include <algorithm>

#define min(a,b) a<b?a:b
using namespace std;

int n;
vector<int> edge[10'001];
vector<int> color;
int dp[10'001][15];
int color_size;

int tree_dp(int cur, int prev, int prev_color) {
	int min_val = 1e9;
	bool flag = 1;
	for (int i = 0; i < color_size; i++) {
		if (i == prev_color) continue;
		if (!dp[cur][i]) flag = 0;
		min_val = min(min_val, dp[cur][i]);
	}
	if (flag) return min_val;


	int next;
	min_val = 1e9;
	for (int cur_color = 0; cur_color < color_size; cur_color++) {
		if (cur_color == prev_color) continue;

		dp[cur][cur_color] = color[cur_color];
		for (int i = 0; i < edge[cur].size(); i++) {
			next = edge[cur][i];
			if (next == prev) continue;

			dp[cur][cur_color] += tree_dp(next, cur, cur_color);
		}
		min_val = min(min_val, dp[cur][cur_color]);
	}

	return min_val;
}

void solution() {
	int n1, n2, m, min_val = 1e9;
	int max_color = 15;

	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		cin >> n1 >> n2;
		edge[n1].push_back(n2);
		edge[n2].push_back(n1);
	}

	cin >> m;
	color_size = m < max_color ? m : max_color;
	for (int i = 0; i < m; i++) {
		cin >> n1, color.push_back(n1);
	}
	sort(color.begin(), color.end());

	for (int i = 0; i < color_size; i++) min_val = min(min_val, tree_dp(1, 0, i));

	cout << min_val;
}

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

	return 0;
}
메모리: 3412 kb 시간: 12 ms