https://www.acmicpc.net/problem/2655
- 벽돌은 회전시킬 수 없다. 즉, 옆면을 밑면으로 사용할 수 없다.
- 밑면의 넓이가 같은 벽돌은 없으며, 또한 무게가 같은 벽돌도 없다.
- 벽돌들의 높이는 같을 수도 있다.
- 탑을 쌓을 때 밑면이 좁은 벽돌 위에 밑면이 넓은 벽돌은 놓을 수 없다.
- 무게가 무거운 벽돌을 무게가 가벼운 벽돌 위에 놓을 수 없다.
위의 조건을 만족하면서 가장 높게 탑을 쌓아야한다. 입력으로 주어지는 벽돌의 개수가 100개 이하이므로 모든 경우의 수를 다 훓어보기에 충분하다.
훓을때 고려해야할 조건이 무게가 높은 블럭, 밑면적이 큰 블럭이 밑에 쌓여야만 한다.
본인은 밑면적 순으로 정렬해서 탐색할때 밑면적이 큰 놈이 밑으로 오게 하고 무게 조건은 if문으로 처리했다.
Dp[i]가 i개의 벽돌을 사용했을 때 가능한 가장 큰 높이가 아니다.
i번째 벽돌을 무조건 사용했을때 가능한 가장 큰 높이로 해야한다.
이유는 출력해야하는 값이 가장 높을때의 탑의 높이가 아니라 탑이 가장 높을때 몇번째 벽돌을 사용했는지를 출력해야하므로 벽돌에 id값을 붙여서 출력할때 써먹어야한다...출력을 위해 어떤 Dp로 수행할 건지 정해야하는 어려운문제...
정확하게 왜 dp를 i번째 벽돌을 무조건 사용했을때 가능한 가장 큰 높이로 해야하는지는 코드를 보고 출력을 위해 벽돌 번호를 어떻게 꺼냈는지 보면 이해할 수 있을 것이다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define endl "\n"
using namespace std;
struct Brick {
int a, h, w, num;
};
bool compare(Brick x, Brick y){
return x.a < y.a;
}
int main() {
int n;
cin >> n;
vector<Brick> brick;
Brick start = {0,0,0,0};
brick.push_back(start);
for(int i = 1; i <= n; i++){
Brick b;
cin >> b.a >> b.h >> b.w;
b.num = i;
brick.push_back(b);
}
sort(brick.begin(),brick.end(),compare);
int dp[101], height = 0;
memset(dp,0,sizeof(dp));
//i번째 블록을 무조건 사용했을때 가능한 가장 높은 탑
for(int i = 1; i <= n; i++){
for(int j = 0; j < i; j++){
if(brick[i].w > brick[j].w){
dp[i] = max(dp[i],dp[j]+brick[i].h);
}
}
height = max(height,dp[i]);
}
vector<int> ans;
for(int i = n; i > 0 ; i--){
if(dp[i] == height){
ans.push_back(brick[i].num);
height -= brick[i].h;
}
}
cout << ans.size() << endl;
reverse(ans.begin(),ans.end());
for(auto v : ans) cout << v << endl;
}
'📚알고리즘 > 백준' 카테고리의 다른 글
[백준 7453번] 합이 0인 네 정수 (C++) (0) | 2024.07.21 |
---|---|
[백준 31443번] 준영이 (C++) (0) | 2024.07.17 |
[백준 24025번] 돌의 정령 줄세우기 (C++) (0) | 2024.07.16 |
[백준 7561번] 크래머의 공식 (C++) (0) | 2024.07.06 |
[백준 31404번] 아리스, 청소합니다! (Easy) (C++) (0) | 2024.07.03 |