λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

μ•Œκ³ λ¦¬μ¦˜ 문제

2240 - μžλ‘λ‚˜λ¬΄

문제boj.kr/2240
λ‚ μ§œ: 09/20 (금)
성곡여뢀: X [02:20:01]

 

μžλ‘ λ‚˜λ¬΄μ—μ„œ λ–¨μ–΄μ§€λŠ” μžλ‘λ₯Ό μ΅œλŒ€ W만큼 움직여 μ΅œλŒ€ν•œ λ§Žμ€ μžλ‘λ₯Ό λ¨ΉλŠ” λ¬Έμ œμ΄λ‹€.

 

μ™„μ „ 탐색

μžλ‘ λ‚˜λ¬΄λŠ” 각각 2개의 μœ„μΉ˜μ— 있고, μ‹œκ°„ λ³„λ‘œ λ‘˜ 쀑 ν•˜λ‚˜μ˜ λ‚˜λ¬΄μ—μ„œ μžλ‘κ°€ λ–¨μ–΄μ§„λ‹€. κ°€μž₯ κ°„λ‹¨ν•˜κ²Œ 생각해볼 수 μžˆλŠ” 방법은 μ—­μ‹œ μ™„μ „ 탐색이닀.

 

μ—¬κΈ°μ„œ μ£Όμ–΄μ§€λŠ” λ³€μˆ˜λ₯Ό 생각해보면 μ‹œκ°„, 이동 횟수, μœ„μΉ˜κ°€ μžˆλ‹€. μžλ‘κ°€ μ²˜μŒμ— 1 μœ„μΉ˜μ—μ„œ μ‹œμž‘ν•˜λ‹ˆκΉŒ ν•΄λ‹Ή μœ„μΉ˜λ₯Ό κΈ°μ€€μœΌλ‘œ 이동 횟수λ₯Ό μ†Œλͺ¨ν•˜μ§€ μ•Šκ³  μ œμžλ¦¬μ— μžˆλŠλƒ ν˜Ήμ€ 이동 횟수λ₯Ό μ†Œλͺ¨ν•΄μ„œ 1 μœ„μΉ˜λ‘œ μ΄λ™ν•˜λŠλƒ 두 κ°€μ§€ 경우의 μˆ˜κ°€ μžˆλ‹€. 그럼 λ‹€μŒκ³Ό 같이 두 번의 호좜이 ν•„μš”ν•¨μ„ μ˜ˆμƒν•  수 μžˆλ‹€.

go(t + 1, w, 0);

go(t + 1, w-1, 1);

 

ν•˜λ‚˜μ˜ μœ„μΉ˜μ—μ„œ μ‹œκ°„μ˜ 흐름에 따라 2κ°€μ§€μ˜ 갈래둜 λ‚˜λ‰˜λ‹ˆκΉŒ ν•΄λ‹Ή 둜직의 μ‹œκ°„ λ³΅μž‘λ„λŠ” μ΅œμ†Œ 2^30 μž„μ„ μ•Œ 수 μžˆλ‹€. μ™œλƒλ©΄ wκ°€ μ΅œλŒ€ 30이기 λ•Œλ¬Έμ΄λ‹€. 움직이지 μ•ŠλŠ” 경우의 수둜만 보면 T의 μ΅œλŒ€μΈ 1000κΉŒμ§€λ„ κ°€λŠ₯ν•˜λ‹€. 2^30(μ•½ 10μ–΅)만 해도 이미 λ„ˆλ¬΄ 큰 수이기 λ•Œλ¬Έμ— μ™„μ „ νƒμƒ‰μœΌλ‘œλŠ” λΆˆκ°€λŠ₯ν•˜λ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€.

 

κ·Έλž˜μ„œ μ‹œκ°„μ„ 쀄일 방법이 μ—†μ„κΉŒν•΄μ„œ 직접 μ™„μ „ νƒμƒ‰μ˜ 흐름을 μ‘°κΈˆμ΄λ‚˜λ§ˆ μ«“μ•„κ°”λ‹€.

 

ν•΄λ‹Ή 사진을 보면 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄λ‘œ 처음 DPλ₯Ό 배웠을 λ•Œμ²˜λŸΌ ν•¨μˆ˜μ˜ ν˜ΈμΆœμ—μ„œ κ½€λ‚˜ λ§Žμ€ λΆ€λΆ„μ˜ 흐름이 κ²ΉμΉœλ‹€. 이λ₯Ό 톡해 DP둜 ν’€ 수 μžˆμ„ 것 κ°™λ‹€κ³  μƒκ°ν–ˆλ‹€.

 

DP

μ²˜μŒμ—” 2차원 DP λ°°μ—΄μ—μ„œ w, tλ₯Ό κ°€μ§€κ³  λ‚˜μ€‘μ—λŠ” t, hλ‚˜ w, hλ‘œλ„ ν’€λ €κ³  ν–ˆμœΌλ‚˜ μ—­λŸ‰ λΆ€μ‘±μœΌλ‘œ ν’€μ§„ λͺ»ν–ˆλ‹€. κ·Έλž˜μ„œ λ‹€λ₯Έ λΈ”λ‘œκ·Έλ“€μ˜ 해섀을 λ΄€λ‹€.. 그리고, λ‚˜λ§Œμ˜ λ°©λ²•μœΌλ‘œ λ‹€μ‹œ ν•œλ²ˆ ν‘ΈλŠ” 것에 μ„±κ³΅ν–ˆκ³  κ·Έ 풀이 과정을 μ„€λͺ…ν•˜κ² λ‹€.

 

일단 μƒˆλ‘œμš΄ 예제λ₯Ό ν•œλ²ˆ μƒκ°ν•΄λ³΄μž.

3 2
2
1
1

 

t = 3, w = 2κ°€ μ£Όμ–΄μ§€κ³  t=1일 λ•Œ 2, t=2일 λ•Œ 1, t=3일 λ•Œ 1 μœ„μΉ˜μ—μ„œ 각각 μžλ‘κ°€ λ–¨μ–΄μ§„λ‹€. ν•΄λ‹Ή 예제λ₯Ό μ™„μ „ νƒμƒ‰μœΌλ‘œ 흐름을 μ«“μ•„κ°€λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

 

 

일단 μœ„μ˜ 그림을 ν†΅ν•΄μ„œλ„ μ•Œ 수 μžˆλ“―μ΄ ν•΄λ‹Ή λ¬Έμ œμ—μ„œ μ£Όμ–΄μ§„ λ³€μˆ˜λŠ” 총 3가지이닀. μžλ‘κ°€ λ–¨μ–΄μ§€λŠ” μ‹œκ°„, 이동 횟수, μžλ‘μ˜ μœ„μΉ˜. μ—¬κΈ°μ„œ μš°λ¦¬κ°€ κ΅¬ν•΄μ•Όν•˜λŠ” 것은 먹은 μžλ‘μ˜ κ°―μˆ˜μ΄λ‹€. νŽΈμ˜μƒ μžλ‘κ°€ λ–¨μ–΄μ§€λŠ” μœ„μΉ˜λŠ” 1,2κ°€ μ•„λ‹Œ 0,1둜 ν•œλ‹€.

 

t = 3, w = 2, h = 0일 λ•ŒλŠ” t=2, w=2, h=0κ³Ό t=2, w=1, h=1둜 경우의 수λ₯Ό λ‚˜λˆŒ 수 있고 t = 2, w = 2, h = 0일 λ•ŒλŠ” t = 1, w = 2, h = 0κ³Ό t = 1, w= 1, h = 1인 경우둜 λ‚˜λˆŒ 수 μžˆλ‹€. 이λ₯Ό μΌλ°˜ν™”ν•˜λ©΄ t, w, h에 λŒ€ν•΄ λ‚˜λˆŒ 수 μžˆλŠ” 경우의 μˆ˜κ°€ (t-1, w, h)와 (t-1, w-1, h^1)μž„μ„ μ•Œ 수 μžˆλ‹€.

 

t = 0일 λ•ŒλŠ” μ‹œκ°„μ΄ λͺ¨λ‘ μ†Œμ§„λœ κ²ƒμ΄λ―€λ‘œ 먹을 수 μžˆλŠ” μžλ‘ κ°œμˆ˜κ°€ 0이닀. 그럼 κ°€μž₯ μ•„λž«λ‹¨ t = 0일 λ•Œ λ°˜ν™˜λ˜λŠ” μžλ‘μ˜ κ°œμˆ˜λŠ” 0이닀. 

if (t <= 0) return 0;

 

그리고 t = 1일 λ•Œ μžλ‘λŠ” 1의 μœ„μΉ˜μ—μ„œ λ–¨μ–΄μ§€λ―€λ‘œ t = 1, w = 2, h = 0μ—μ„œ λ¨ΉλŠ” μžλ‘ κ°œμˆ˜λŠ” 0이닀. t = 1, w = 1, h = 1μ—μ„œ λ¨ΉλŠ” μžλ‘ κ°œμˆ˜λŠ” 1이닀. 그럼 이 두 값이 λ°˜ν™˜λ˜κ³  t = 2, w = 2, h = 0μ—μ„œ 두 κ°’ 쀑 μ΅œλŒ“κ°’μ„ μ„ νƒν•˜λ©΄ λœλ‹€. μ—¬κΈ°κΉŒμ§€ μ™”μœΌλ©΄ λŒ€μΆ© 이런 μ½”λ“œλ₯Ό 생각할 수 μžˆλ‹€. 그리고 t = 2μ—μ„œ μœ„μΉ˜μ— 따라 μžλ‘λ₯Ό 먹을 수 μžˆλ‹€λ©΄ +1 μ•„λ‹ˆλ©΄ +0을 ν•˜λ©΄ λœλ‹€.

 

if (t <= 0) return 0;

return Math.max(go(t-1, h^1, w-1), go(t-1, h, w)) + (tree[t] == h ? 1 : 0);

 

이 흐름을 따라 계속 타고 μ˜¬λΌκ°€λ‹€λ³΄λ©΄ μ΅œλŒ€ν•œ 먹을 수 μžˆλŠ” μžλ‘ κ°œμˆ˜κ°€ λ‚˜μ˜¨λ‹€. μ—¬κΈ°μ„œ 이제 DPλ₯Ό μ΄μš©ν•΄μ„œ κ²ΉμΉ˜λŠ” 뢀뢄에 λŒ€ν•œ 문제λ₯Ό 미리 κΈ°λ‘ν•΄λ†“μ•˜λ‹€κ°€ ν•„μš” μ‹œμ— μ‚¬μš©ν•˜λ©΄ λœλ‹€!! 즉, return λ˜λŠ” μžλ‘μ˜ 개수λ₯Ό DP 배열에 μ €μž₯ν•˜λŠ” 것이닀.

 

if (t <= 0) return 0;

dp[t][h][w] = Math.max(go(t-1, h^1, w-1), go(t-1, h, w)) + (tree[t] == h ? 1 : 0);
return dp[t][h][w];

 

μœ„μ˜ κ·Έλ¦Όμ—μ„œλŠ” t=1, w=1, h=1 λ¬Έμ œκ°€ κ²ΉμΉ˜λŠ”λ°, 이 λ•Œ 먹을 수 μžˆλŠ” μžλ‘ κ°œμˆ˜λŠ” 1κ°œκ°€ μ΅œλŒ€μž„μ„ 이미 κ΅¬ν–ˆμœΌλ―€λ‘œ t=2, h=1, w=1은 ν•΄λ‹Ή 경우의 수λ₯Ό κ΅¬ν•˜μ§€ μ•Šκ³  λ°”λ‘œ DP에 μ €μž₯된 값을 μ΄μš©ν•˜λ©΄ λœλ‹€.

 

if (t <= 0) return 0;
if (dp[t][h][w]에 값이 μžˆλ‹€λ©΄) return dp[t][h][w];

dp[t][h][w] = Math.max(go(t-1, h^1, w-1), go(t-1, h, w)) + (tree[t] == h ? 1 : 0);
return dp[t][h][w];

 

이러면 ν•΄λ‹Ή 문제의 핡심 둜직이 λ‚˜μ™”λ‹€! 이제 λ§ˆμ§€λ§‰μœΌλ‘œ w에 λŒ€ν•΄μ„œ μ²˜λ¦¬ν•΄μ£ΌκΈ°λ§Œ ν•˜λ©΄ λœλ‹€. wλŠ” 0일 λ•ŒκΉŒμ§€λŠ” μžλ‘λ₯Ό 먹을 수 μžˆμœΌλ―€λ‘œ 0보닀 μž‘μ•„μ§„ μˆœκ°„λΆ€ν„°λŠ” μ•„μ˜ˆ λΆˆκ°€λŠ₯ν•œ κ²½μš°μ΄λ‹€. 즉, μžλ‘ κ°œμˆ˜μ— 영ν–₯을 쀄 수 μ—†λ‹€. κ·ΈλŸ¬λ―€λ‘œ 0을 returnν•˜μ—¬ μžλ‘ κ°œμˆ˜μ— 영ν–₯을 μ£Όμ§€ μ•Šλ„λ‘ ν•œλ‹€!

 

if (t <= 0 || w < 0) return 0;
if (dp[t][h][w]에 값이 μžˆλ‹€λ©΄) return dp[t][h][w];

dp[t][h][w] = Math.max(go(t-1, h^1, w-1), go(t-1, h, w)) + (tree[t] == h ? 1 : 0);
return dp[t][h][w];

 

μ½”λ“œ

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
    // μ‹œκ°„μ œν•œ 2초, λ©”λͺ¨λ¦¬μ œν•œ 128MB
    static int T, W;
    static int[] tree;
    static int[][][] dp;

    static int go(int t, int h, int w) {

        if (t <= 0 || w < 0) return 0;
        if (dp[t][h][w] != -1) return dp[t][h][w];

        dp[t][h][w] = Math.max(go(t-1, h^1, w-1), go(t-1, h, w)) + (tree[t]-1 == h ? 1 : 0);
        return dp[t][h][w];
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        T = Integer.parseInt(st.nextToken());
        W = Integer.parseInt(st.nextToken());

        tree = new int[T+1];
        tree[0] = 0;
        for (int i = 1; i <= T; i++) tree[i] = Integer.parseInt(br.readLine());

        dp = new int[T+1][2][W+1];
        // -1둜 μ΄ˆκΈ°ν™” ν•˜μ§€μ•ŠμœΌλ©΄ dp 값듀이 0이 λ˜λŠ”λ°,
        // 0으둜 dp 값이 μ‘΄μž¬ν•˜λŠ”μ§€ μ—¬λΆ€λ₯Ό μ •ν•΄μ£Όλ©΄ 아직 κ΅¬ν•˜μ§€ μ•Šμ€ 경우의 μˆ˜μ— λŒ€ν•΄μ„œ return dp[t][h][w];κ°€ μ‹€ν–‰λœλ‹€.
        for (int i = 0; i <= T; i++) {
            for (int j = 0; j < 2; j++) Arrays.fill(dp[i][j], -1);
        }

        System.out.println(Math.max(go(T, 0, W), go(T, 1, W-1)));
    }
}

 

'μ•Œκ³ λ¦¬μ¦˜ 문제' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

2293 - 동전 1  (2) 2024.09.23
2294번 문제 λ©”λͺ¨  (0) 2024.09.22
2098 - μ™ΈνŒμ› 순회  (2) 2024.09.17
2565 - 전깃쀄  (1) 2024.09.12
1561 - 놀이 곡원  (2) 2024.09.09