백준 2655번 가장 높은 탑 쌓기

2021. 1. 20. 04:52Algorithm/문제풀이

백준 2655번 - 가장 높은 탑 쌓기

가장 높은 탑 쌓기 문제의 경우 전형적인 dp문제 중 하나이다. 조건 중 하나가 밑의 블럭의 크기와 무게가 현재 블럭 보다 더 커야 한다는 조건이 있다. 이전의 위치한 블럭의 값 들과 계속해서 비교하면서 값을 업데이트해준다.

 

우선 시작하기전에 필자의 경우에는 넓이의 기준으로 내림차순으로 정렬했다. (물론 무게를 기준으로 정렬해도 된다.) 그래서 블럭의 이전의 값들과 비교하기 편하다. 내림차순이면 이전의 넓이는 항상 큰 값이 된다.

 

따라서 점화식은 아래와 같다.  dp[i] i번째 블럭의 가장 높은 높이이다.

if(올릴 수 있는 블럭이라면) { // 현재 블럭이 더 가볍고 부피가 작다면
	dp[now] = max(dp[now], dp[prev] + height[now]);
}

 

문제가 가장 높은 높이를 구하는 문제였으면 dp값 중 가장 큰 값을 출력하면 되지만 이 문제의 경우 가장 큰 값을 찾아가는 tracking이 필요했다. 그래서 Dp에 이전의 인덱스를 저장해서 해결해주었다. 

 

더보기
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

vector<pair<int, int> > dp(103);
vector<pair<int, pair<int, int> > > sub;
vector<pair<int, pair<int, int> > > order;
vector<int> result;

void solve();
bool isCorrectBox(int prev, int now);

int N;
int main(){	
	int area, height, weight;
	scanf("%d", &N);
	for(int i = 0; i < N; i++){
		scanf("%d %d %d", &area, &height, &weight);
		sub.push_back(make_pair(area, make_pair(height, weight)));
		order.push_back(make_pair(area, make_pair(height, i)));
	}

	sort(sub.begin(), sub.end(), greater<pair<int, pair<int, int> > >());
	sort(order.begin(), order.end(), greater<pair<int, pair<int, int> > >());
	solve();
}

void solve(){
	dp[0].first = sub[0].second.first;
	dp[0].second = 0;


	for(int now = 1; now < N; now++){
		dp[now].first = sub[now].second.first;
		for(int prev = 0; prev < now; prev++){
			if(isCorrectBox(prev, now)){
				if(dp[now].first < dp[prev].first + sub[now].second.first){
					dp[now].first = dp[prev].first + sub[now].second.first;
					dp[now].second = prev;
				}
			}
		}
	}

	// dp 코드

	int maxValue = 0, maxIndex;

	for(int i = 0; i < N; i++){
		if(maxValue < dp[i].first){
			maxValue = dp[i].first;
			maxIndex = i;
		}
	}

	int compareNum = 0;

	while(maxValue !=  compareNum){
		result.push_back(order[maxIndex].second.second);
		compareNum +=order[maxIndex].second.first;
		maxIndex = dp[maxIndex].second;
	}

	printf("%d\n", result.size());

	for(auto rank : result){
		printf("%d\n", rank+1);
	}
}


bool isCorrectBox(int prev, int now){
	if(sub[now].first < sub[prev].first && sub[now].second.second < sub[prev].second.second)
		return true;
	return false;
}

 

'Algorithm > 문제풀이' 카테고리의 다른 글

백준 1563 개근상  (0) 2021.01.22
백준 개미굴 14725  (0) 2021.01.20
백준 9465 스티커  (0) 2021.01.13
백준 14501 퇴사  (0) 2021.01.13
백준 11052 카드 구매하기  (0) 2021.01.13