백준 14002
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.
앞에서 작성했던 가장 긴 증가하는 부분 수열의 심화버전의 문제이다. (이전문제는 아래 링크로 들어가면 된다)
2020/07/22 - [백준 문제풀이] - 가장 긴 증가하는 부분 수열_ 백준11053
위 문제에서 조금 더 어려워 진 점은, 가장 긴 증가하는 부분 수열을 출력해야하는 점이다.
즉, 수열의 순서를 저장할 필요가 있는 것인데, 나는 11053 문제의 코드에 더 덧붙이는 방식으로 풀었으므로 (두 문제의 연관성이 크므로, 이 순서로 푸는 것을 추천한다) 11053 문제에서 생각했던 점화식의 흐름에 초점을 맞추어 진행했다.
각각의 부분수열을 저장할 수는 없으므로, d[i]를 구하면서, 하나의 배열을 추가하여 그 흐름을 활용하는 것이 필요하다.
즉, 가장 긴 부분수열을 찾는 과정에서 우리는 d[i]앞에 이어지는 부분인 d[j]를 찾으므로,
i앞에 오는 j를 prev 배열에 저장하고 그것을 역순으로 찾아가면 가장 긴 증가하는 부분수열을 찾을 수 있게 되는 것이다.
다만, 나같은 경우는 이러한 논리를 세워 문제를 풀었음에도 몇번 틀렸는데,
추가적인 테스트케이스를 서치해서 돌린 이후에 코드를 수정했다.
4
4 1 2 3
[답 :: 3, 1 2 3]
4
1 3 4 2
[답 :: 3, 1 3 4]
6
4 5 6 1 2 3
[답 :: 3, 1 2 3] (오른쪽 1 2 3은 4 5 6이 될 수 도있고 여러 답이 될 수 있다.
6
4 9 11 5 7 8
[답 :: 4, 4 5 7 8]
8
1 6 2 5 7 3 5 6
[답 :: 5, 1 2 3 5 6]
9
3 1 2 4 7 5 6 8 10
[답 :: 7, 1 2 4 5 6 8 10]
출처: https://www.crocus.co.kr/681 [Crocus]
또한, 나는 배열에 다시 넣어서 역순으로 출력했는데, 사실 스택으로 하는 것이 더 효율적인 방법으로 보인다.
편하다고 계속 배열을 쓰는 버릇을 고치는게 필요할 것 같다.
#include <cstdio>
using namespace std;
int nums[1001];
int d[1001];
int prev[1001];
int result[1001];
int main(void)
{
int num;
int biggest = 0;
int idx = 0;
int count = 0;
int p;
scanf("%d", &num);
for (int i = 0; i < num; i++)
{
scanf("%d", &nums[i]);
}
for (int i = 0; i < num; i++)
{
d[i] = 1;
prev[i] = i;
for (int j = 0; j < i; j++)
{
if (nums[j] < nums[i] && d[i] < d[j] + 1)
{
d[i] = d[j] + 1;
prev[i] = j;
}
}
if (biggest < d[i])
{
idx = i;
biggest = d[i];
}
}
printf("%d\n", biggest);
for (p = idx; p != prev[p]; p = prev[p])
result[count++] = nums[p];
result[count] = nums[p];
for (int i = count; i > -1; i--)
{
printf("%d ", result[i]);
}
}
'백준 문제풀이' 카테고리의 다른 글
[c++/백준] 1697 숨바꼭질 (0) | 2020.08.21 |
---|---|
연속합 _백준 1912 (0) | 2020.07.24 |
가장 긴 증가하는 부분 수열_ 백준11053 (0) | 2020.07.22 |
이친수_2193 (0) | 2020.05.29 |
쉬운 계단 수 _ 백준 10844 (0) | 2020.05.29 |