알고리즘/BOJ

[BOJ] 백준 9465번: 스티커

벨에삐 2023. 2. 26. 02:02

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

 

9465번: 스티커

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 n (1 ≤ n ≤ 100,000)이 주어진다. 다음 두 줄에는 n개의 정수가 주어지며, 각 정수는 그 위치에 해당하는 스티커의

www.acmicpc.net

이번에도 DP 기본 문제입니다.

 

#include <bits/stdc++.h>
using namespace std;

int T, n, score[3][100001], dp[100001][3];

void solve(){
	dp[1][0] = 0;
	dp[1][1] = score[1][1];
	dp[1][2] = score[2][1];
	
	for(int i = 2; i <= n; ++i){
		dp[i][0] = max(dp[i-1][1], dp[i-1][2]);
		dp[i][1] = max(dp[i-1][0], dp[i-1][2]) + score[1][i];
		dp[i][2] = max(dp[i-1][0], dp[i-1][1]) + score[2][i]; 
	}
	
	cout << max(dp[n][1], dp[n][2]) << '\n';
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> T;
	
	while(T--){
		cin >> n;
		for(int i = 1; i <= 2; ++i){
			for(int j = 1; j <= n; ++j){
				cin >> score[i][j];
			}
		}
		solve();
	}
}

 

이번에도 1) table 정의 2) 점화식 찾기 3) 초기값 설정의 3단계로 일관성 있게 구현했습니다.

 

1) table 정의 
dp[i][k] : i번째 열에서 k의 선택을 할 때 스티커 점수의 합의 최대값 
(k = 0 : 아무것도 안고름, k = 1 : 첫번째 행 스티커 고름, k = 2 : 두번째 행 스티커 고름)


2) 점화식 찾기
dp[i][0] = max(dp[i-1][1], dp[i-1][2]);  
dp[i][1] = max(dp[i-1][0], dp[i-1][2]) + score[1][i];
dp[i][2] = max(dp[i-1][0], dp[i-1][1]) + score[2][i];  


3) 초기값 설정
dp[1][0] = 0;
dp[1][1] = score[1][1];
dp[1][2] = score[2][1]; 

 

자교 문병로 교수님께서 쓰신 쉽게 배우는 알고리즘에 이와 비슷한 돌놓기 문제가 소개되어 있어 공부한 적이 있는데, case를 나눠서 풀이하는 방식이 직관적으로 다가와 쉽게 풀 수 있었습니다. 

 

살짝 고민했던 부분은 dp[i][0] = max(dp[i-1][1], dp[i-1][2]); 부분입니다. 

dp[i-1][0]까지도 비교를 해줘야하나 싶었는데 스티커 점수가 음이 아닌 정수이므로 스티커를 선택하는 dp[i-1][1] 또는 dp[i-1][2]가 스티커를 선택하지 않는 dp[i-1][0]보다 값이 클 수 밖에 없어 비교가 불필요합니다. 따라서 출력하는 값이  *max_element(dp[n], dp[n]+3) 이어도 올바른 답을 출력하지만, dp[n][0]은 항상 dp[n][1], dp[n][2]보다 작으므로 max(dp[n][1], dp[n][2]) 으로 충분한 것입니다.

 

경험상 어떤 제약이 있거나 추가 조건이 있을 때 1차원의 table로는 풀이하기 어려운 경우가 많은데 2차원, 3차원, 4차원 등으로 table의 차원을 늘려 이런 조건들을 처리해주면 유용했습니다.

 

시간복잡도 O(n) 입니다.

'알고리즘 > BOJ' 카테고리의 다른 글

[BOJ] 백준 2193번: 이친수  (0) 2023.02.26
[BOJ] 백준 2294번: 동전 2  (0) 2023.02.26
[BOJ] 백준 1463번: 1로 만들기  (0) 2023.02.26
[BOJ] 백준 2357번: 최솟값과 최댓값  (0) 2023.02.24
[BOJ] 백준 10868번: 최솟값  (0) 2023.02.24