ahlight
개발 저장소
ahlight
전체 방문자
오늘
어제
  • 분류 전체보기 (197)
    • Java (7)
    • Spring (5)
    • JPA (2)
    • JavaScript (0)
    • Computer Science (12)
      • 디자인패턴, 프로그래밍 패러다임 (1)
      • 네트워크 (4)
      • 운영체제 (4)
      • 데이터베이스 (3)
      • 자료구조 (0)
    • 알고리즘 (1)
    • 프로그래머스 (13)
    • 백준 (94)
    • 서평 (3)
    • 회고 (1)
    • TIL (58)
    • 기타 (1)

블로그 메뉴

  • 홈

공지사항

인기 글

태그

  • 라즈베리파이4 #홈서버 #포트포워딩 #dhcp
  • 넥스트스텝
  • 클린코드
  • TDD
  • Java

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ahlight

개발 저장소

백준

백준 2228번 자바 ☆☆

2022. 12. 28. 11:22

문제

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

 

2228번: 구간 나누기

N(1 ≤ N ≤ 100)개의 수로 이루어진 1차원 배열이 있다. 이 배열에서 M(1 ≤ M ≤ ⌈(N/2)⌉)개의 구간을 선택해서, 구간에 속한 수들의 총 합이 최대가 되도록 하려 한다. 단, 다음의 조건들이 만족되

www.acmicpc.net

import java.util.Scanner;

public class Main {

	static int N,M;
	static int[] arr;
	static int[] sum;
	static int[][] dp;
	
	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		
		N = sc.nextInt();
		M = sc.nextInt();
		arr = new int[N+1];
		sum = new int[N+1];
		dp = new int[M+1][N+1];
		
		for (int i=1; i<=N; i++) {
			arr[i] = sc.nextInt();
		}
		
		sum[1] = arr[1];
		for (int i=2; i<=N; i++) {
			sum[i] = sum[i-1] + arr[i];
		}
		
		for (int i=1; i<=M; i++) {
			for (int j=0; j<=N; j++) {
				dp[i][j] = Integer.MIN_VALUE/2;
			}
		}

		dp[1][1] = arr[1];
		for (int i=1; i<=M; i++) {
			for (int j=2; j<=N; j++) {
				dp[i][j] = dp[i][j-1];
				
				int min = 0;
				if (i == 1) {
					min = -1;
				}
				for (int k=j-2; k>=min; k--) {
					if (k < 0) {
						dp[i][j] = Math.max(dp[i][j], sum[j]);
					} else {
						dp[i][j] = Math.max(dp[i][j], dp[i-1][k] + (sum[j] - sum[k+1]));
					}
				}
			}
		}
		
		System.out.println(dp[M][N]);
	}
}

1. 문제 풀이에 대한 자세한 내용은 아래 타 블로그 주소를 첨부했다.

 

2. 해당 문제를 풀며 헤맸던 부분을 추가로 작성한다.

 첫째, 문제에 대한 이해도.

 문제 내용이 애매한건지 내 문해력이 낮은건지는 잘 모르겠다. 다만 문제 내용중 '각 구간은 한 개 이상의 연속된 수들로 이루어진다.' 이 부분이 1,2,3,4처럼 연속된 정수로 이루어진다고 이해했다. 그러다보니 문제에 대하 접근자체가 완전히 엉뚱한 길로 들어가고 체감 난이도가 높아졌다.

 

 둘째, dp[i][j]의 초기값은 왜 Integer.MIN_VALUE/2 일까?

 먼저 N의 최대 길이는 100, 배열 N의 각 원소들의 값은 -32768 ~ 32767 사이의 정수다. 그렇다면 각 배열의 원소가 모두 -32768일 경우 가장 작은 구간합은 -32768 * 100이 된다. 그렇기에 넉넉하게 Integer.MIN_VALUE/2로 초기값을 설정한 것이다. 그렇다면 왜 2로 나눴을까? 점화식에서 오버플로우가 발생할 수 있기때문이다. 이 부분을 이해하는데 많이 헤맸다.

 

 셋째, dp[i][j] 초기화 시 왜 j는 0부터 시작할까?

 j값이 1부터 시작한다면 j=0일때 dp[i][j]는 당연히 0으로 초기화 될 것이다. 하지만 j=0이라는 뜻은 M개의 구간에서 N이 하나도 없는 경우이다. 구간합이 0이 될수도 있기 때문에 N이 하나도 없는 경우는 Integer.MIN_VALUE/2로 초기화 되어야 이후 점화식에서 올바른 답이 도출 될 수 있다.  

 

정리 : 문제이해도부터 해답을 찾는 과정까지 쉽지 않았다. 오랜만에 어떻게 해야할지 감이 전혀 안잡혔던 문제다. 또 다른 블로그들의 코드를 봐도 명확하게 이해가 되지 않았다. 다음번에 꼭 다시 풀어봐야하는 문제다.

 

 

참고 및 출처 : https://lotuslee.tistory.com/116

'백준' 카테고리의 다른 글

백준 2018번 자바  (2) 2022.12.29
백준 10986번 자바 ☆  (0) 2022.12.28
백준 1937번 자바  (1) 2022.12.22
백준 14002번 자바  (0) 2022.12.22
백준 11053번 자바 ☆  (0) 2022.12.20
    '백준' 카테고리의 다른 글
    • 백준 2018번 자바
    • 백준 10986번 자바 ☆
    • 백준 1937번 자바
    • 백준 14002번 자바
    ahlight
    ahlight

    티스토리툴바