문제 정보
https://www.acmicpc.net/problem/1744
1744번: 수 묶기
길이가 N인 수열이 주어졌을 때, 그 수열의 합을 구하려고 한다. 하지만, 그냥 그 수열의 합을 모두 더해서 구하는 것이 아니라, 수열의 두 수를 묶으려고 한다. 어떤 수를 묶으려고 할 때, 위치에
www.acmicpc.net
난이도 : G4
유형 : DP
시간 : O(N), 정렬시간 제외
해결 방법
모든 수는 최대 한 번만 묶일 수 있다.
연속이 아닌 부분 수열의 합을 구하는 것이므로 수열의 원소의 위치가 변경돼도 상관없다. -> 정렬 가능
1. 직관적으로 큰 수끼리 곱해야 더 큰 수가 나오므로 주어진 수열을 정렬한다.
2. 오름차 순으로 정렬 시 왼쪽에서부터 오른쪽으로 진행
3. 탐색하면서 매 순간 dp배열에 가장 큰 값을 대입한다.
dp배열은 매 탐색 중 가장 큰 값이 저장된 배열이다.
더 큰 수를 선택하기 위해서 2가지를 고려해야한다.
1. 수열[i] 와 수열[i-1] 곱 + dp[i - 2]
2. 수열[i] + dp[i-1]
쉽게 말하자면
현재 수를 왼쪽 수와 묶었을 때와 묶지 않았을 때의 값 중 큰 값을 선택하면 된다.
현재 수와 왼쪽 수를 묶었을 때 우리는 왼쪽 수의 이전 값의 가장 큰 값만 알면 되고
현재 수를 묶지 않을 때는 왼쪽 수까지의 가장 큰 값만 알면 된다.
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N;
int[] sequence;
int[] dp;
private void solution() throws IOException {
N = Integer.parseInt(br.readLine());
if (N == 1) {
System.out.println(Integer.parseInt(br.readLine()));
return;
}
sequence = new int[N];
for (int i = 0; i < N; i++) {
sequence[i] = Integer.parseInt(br.readLine());
}
Arrays.sort(sequence);
dp = new int[N + 1];
dp[1] = sequence[0];
for (int i = 2; i <= N; i++) {
dp[i] = Math.max(dp[i - 1] + sequence[i - 1], dp[i - 2] + sequence[i - 2] * sequence[i - 1]);
}
System.out.println(dp[N]);
}
public static void main(String[] args) throws IOException {
Main main = new Main();
main.solution();
}
}
'Algorithm, Problem Solving > 백준(boj)' 카테고리의 다른 글
[백준][Java] 14170 - Counting Haybales (0) | 2024.04.04 |
---|---|
[백준][Java] 2631 - 줄세우기 (1) | 2024.03.23 |
[백준][Java] 6129 - Obstacle Course (0) | 2023.12.11 |
[백준][Java] 2799 - 블라인드 (0) | 2023.12.09 |
[백준][Java] 17175 - 피보나치는 지겨웡~ (0) | 2023.12.07 |
댓글