※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 9465번 문제인 스티커이다.
문제는 아래 링크를 확인하자.
9465번: 스티커
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 n (1 ≤ n ≤ 100,000)이 주어진다. 다음 두 줄에는 n개의 정수가 주어지며, 각 정수는 그 위치에 해당하는 스티커의
www.acmicpc.net
이 문제는 간단한 점화식으로 풀 수 있는 문제이다.
왼쪽에서부터 k번째 칸까지의 점수가 가장 크게 스티커를 잘라내는 케이스를 생각해보자.
k-1번째 칸의 위아래 스티커를 (안 가져갈 수는 있지만) 모두 가져갈 수는 없으므로(문제 조건), k번째 칸에서 스티커를 잘라내지 않고 최댓값을 얻을 수는 없다.
그렇다면 점수가 최대가 되게 스티커를 잘라내는 경우는 k번째 스티커 중 윗칸 스티커를 잘라내면서 최대인 경우, 아랫칸 스티커를 잘라내면서 최대인 경우 두가지중 하나가 된다.
윗칸 스티커를 잘라낼 거라면, 이전 칸의 아랫칸 스티커를 잘라냈거나 이전 칸의 스티커를 가져오지 않아야한다.
아랫칸 스티커를 잘라낼거라면, 이전 칸의 윗칸 스티커를 잘라냈거나 이전 칸의 스티커를 가져오지 않아야한다.
이를 식으로 나타내면 다음과 같다.
(윗칸 스티커 자르는 점수 최댓값)
= max( (전칸 아랫칸까지 점수 최댓값), (전전칸까지 점수 최댓값) ) + 윗칸 스티커 점수
(아랫칸 스티커 자르는 점수 최댓값)
= max( (전칸 윗칸까지 점수 최댓값), (전전칸까지 점수 최댓값) ) + 아랫칸 스티커 점수
이것을 맨 왼쪽 칸에서부터 순서대로 계산해나가면 원하는 결과를 얻을 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
using std::cin;
using std::cout;
using std::max;
int A[100000]; // 윗칸 스티커
int B[100000]; // 아랫칸 스티커
int main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);
int T; // 테스트 케이스 수
cin >> T;
int a, b;
int n;
int x;
for (int i = 0;i < T;i++) {
cin >> n; // 스티커 입력받기
for (int j = 0;j < n;j++) {
cin >> x;
A[j] = x;
}
for (int j = 0;j < n;j++) {
cin >> x;
B[j] = x;
}
a = 0; // 초기화
b = 0;
x = 0;
for (int j = 0;j < n;j++) {
int tempa = max(b, x) + A[j]; // 다음 윗스티커 최댓값 계산
int tempb = max(a, x) + B[j]; // 다음 아랫스티커 최댓값 계산
x = max(a, b); // 다음 계산에 쓸 이번칸 비운 최댓값
a = tempa; b = tempb;
}
cout << max(a, b) << '\n';
}
}
'BOJ' 카테고리의 다른 글
[BOJ 7571 // C++] 점 모으기 (0) | 2021.01.14 |
---|---|
[BOJ 1699 // C++] 제곱수의 합 (0) | 2021.01.13 |
[BOJ 1300 // C++] K번째 수 (0) | 2021.01.11 |
[BOJ 1253 // C++] 좋다 (0) | 2021.01.10 |
[BOJ 1744 // C++] 수 묶기 (0) | 2021.01.09 |