λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
λ°±μ€€/Platinum

[BOJ] 10251 : μš΄μ „ λ©΄ν—ˆ μ‹œν—˜

by Jaeguk 2022. 3. 25.
문제 링크

10251번: μš΄μ „ λ©΄ν—ˆ μ‹œν—˜ (acmicpc.net)

 

10251번: μš΄μ „ λ©΄ν—ˆ μ‹œν—˜

만일 G μ΄ν•˜μ˜ μ—°λ£ŒλŸ‰μœΌλ‘œ sμ—μ„œ tκΉŒμ§€ κ°€λŠ” 것이 κ°€λŠ₯ν•˜λ‹€λ©΄ κ°€λŠ₯ν•œ ν•œ 빨리 λ„μ°©ν–ˆμ„ λ•Œ κ±Έλ¦¬λŠ” μ‹œκ°„μ„, λΆˆκ°€λŠ₯ν•˜λ‹€λ©΄ -1을 좜λ ₯ν•œλ‹€.

www.acmicpc.net

풀이

μ²˜μŒμ—λŠ” κ·Έλž˜ν”„ νƒμƒ‰μœΌλ‘œ 풀어보렀고 ν–ˆλ‹€. 보톡 κ·Έλž˜ν”„νƒμƒ‰μ€ μƒν•˜μ’Œμš°λ‘œ νƒμƒ‰ν•˜μ§€λ§Œ 이건 νŠΉλ³„ν•˜κ²Œ 였λ₯Έμͺ½, μ•„λž˜λ‘œλ§Œ νƒμƒ‰ν•˜λŠ” κ·Έλž˜ν”„ 탐색인 쀄 μ•Œμ•˜λ‹€. κ·Έλž˜μ„œ μš°μ„ μˆœμœ„ 큐λ₯Ό λ§Œλ“€μ–΄μ„œ DP배열에 κΈ°λ¦„μ˜ μ–‘κ³Ό, κ±Έλ¦°μ‹œκ°„μ„ λͺ¨λ‘ μ €μž₯ν•œλ‹€.탐색도쀑 κΈ°λ¦„μ˜ 양이 Gλ₯Ό λ„˜μ–΄κ°€λ©΄ κ·Έ κ²½λ‘œλ‘œλŠ” 더이상 탐색을 ν•˜μ§€ μ•ŠλŠ”λ‹€.

μ΄λ ‡κ²Œ ν•˜λ €ν–ˆλ”λ‹ˆ μš°μ„ μˆœμœ„ 큐에 λ“€μ–΄κ°€μ•Ό ν•  정보듀이 λ„ˆλ¬΄ λ§Žμ•˜λ‹€ 1. μ’Œν‘œ, 2. κΈ°λ¦„μ˜ μ΄λŸ‰, 3. κ±Έλ¦° μ‹œκ°„, 4. λ°©ν–₯ 을 μ €μž₯ν•΄μ•Όν–ˆλ‹€. κ·Έλž˜μ„œ μ˜ˆμ œλŠ” 닡이 λ‚˜μ™”μ§€λ§Œ 제좜 κ²°κ³Ό λ©”λͺ¨λ¦¬ μ΄ˆκ³Όκ°€ 났닀. 잘λͺ»λμŒμ„ κΉ¨λ‹«κ³  μ•Œκ³ λ¦¬μ¦˜ λΆ„λ₯˜λ₯Ό λ΄€λ”λ‹ˆ DPλ‹€. 이게 μ™œ DP지 μ˜μ•„ν–ˆλŠ”λ° DP배열을 DP[yμ’Œν‘œ][xμ’Œν‘œ][λ°©ν–₯μ „ν™˜ 횟수][λ°©ν–₯] μ΄λ ‡κ²Œ λ§Œλ“€λ©΄ 이해가 λœλ‹€. μ—¬κΈ°μ„œ λ°©ν–₯은 0 λ˜λŠ” 1둜 ν‘œμ‹œν•˜κ³  μœ„μ—μ„œ μ™”λŠ”μ§€ μ™Όμͺ½μ—μ„œ μ™”λŠ”μ§€λ₯Ό ν‘œμ‹œν•˜λŠ” μΈλ±μŠ€μ΄λ‹€. λ‚˜λŠ” 0은 μœ„μ—μ„œ 1은 μ™Όμͺ½μ—μ„œ μ˜¨κ²ƒμœΌλ‘œ κ°„μ£Όν–ˆλ‹€. 

예λ₯Ό λ“€μ–΄, DP[y][x][k][0] 은 μ•„λž˜ λ˜λŠ” 였λ₯Έμͺ½μœΌλ‘œ ν•œ μΉΈ 갈 수 μžˆλ‹€. μ—¬κΈ°μ„œ 0은 μœ„μͺ½ λ°©ν–₯μ—μ„œ μ™”λ‹€λŠ” λœ»μ΄λ―€λ‘œ μ•„λž˜μͺ½μœΌλ‘œ 이동할 경우 λ°©ν–₯μ „ν™˜μ€ 생기지 μ•ŠλŠ”λ‹€. κ·ΈλŸ¬λ‚˜ 였λ₯Έμͺ½μœΌλ‘œ 갈 κ²½μš°λŠ” λ°©ν–₯μ „ν™˜μ„ ν•΄μ•Όν•œλ‹€.

즉 DP[y+1][x][k][0]이 λ˜κ±°λ‚˜ DP[y][x+1][k+1]][1]이 λ˜κ±°λ‚˜ λ‘˜μ€‘ ν•˜λ‚˜μ΄λ‹€.

점화식을 μ„Έμ›Œλ³΄λ©΄ μ•„λž˜μ™€ κ°™λ‹€.

DP[i + 1][j][k][0] = min(DP[i + 1][j][k][0], DP[i][j][k][0] + Down[i][j]);
DP[i + 1][j][k + 1][0] = min(DP[i + 1][j][k + 1][0], DP[i][j][k][1] + Down[i][j]);

DP[i][j + 1][k][1] = min(DP[i][j + 1][k][1], DP[i][j][k][1] + Right[i][j]);
DP[i][j + 1][k + 1][1] = min(DP[i][j + 1][k + 1][1], DP[i][j][k][0] + Right[i][j]);

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <stack>
#include <vector>
#include <math.h>
#include <queue>
#include <climits>
#include <algorithm>
#include <iomanip>
#include <map>
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef priority_queue<pair<pair<intint>pair<pair<intint>bool>>vector<pair<pair<intint>pair<pair<intint>bool>>>, greater<pair<pair<intint>pair<pair<intint>bool>>>> Priority_queue;
const int INF = INT_MAX;
const int MAX_N = 100 + 5;
int T;
int M, N, L, G;
int Right[MAX_N][MAX_N];
int Down[MAX_N][MAX_N];
int DP[MAX_N][MAX_N][2 * MAX_N][2];
 
bool is_ok(int y, int x) {
    if (y <= 0 || y > M || x <= 0 || x > N)
        return false;
    return true;
}
void Init() {
    memset(DP, 0x3fsizeof(DP));
    DP[1][1][0][0= DP[1][1][0][1= 0;
}
int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> T;
    while (T--) {
        cin >> M >> N >> L >> G;
        Init();
        for (int i = 1; i <= M; i++) {
            for (int j = 1; j < N; j++) {
                cin >> Right[i][j];
            }
        }
        for (int i = 1; i < M; i++) {
            for (int j = 1; j <= N; j++) {
                cin >> Down[i][j];
            }
        }
        for (int i = 1; i <= M; i++) {
            for (int j = 1; j <= N; j++) {
                for (int k = 0; k < 2 * max(M,N); k++) {
                    if (i + 1 <= M) {//μ•„λž˜λ‘œ μ΄λ™
                        DP[i + 1][j][k][0= min(DP[i + 1][j][k][0], DP[i][j][k][0+ Down[i][j]);
                        DP[i + 1][j][k + 1][0= min(DP[i + 1][j][k + 1][0], DP[i][j][k][1+ Down[i][j]);
                    }
                    if (j + 1 <= N) {//였λ₯Έμͺ½ μ΄λ™
                        DP[i][j + 1][k][1= min(DP[i][j + 1][k][1], DP[i][j][k][1+ Right[i][j]);
                        DP[i][j + 1][k + 1][1= min(DP[i][j + 1][k + 1][1], DP[i][j][k][0+ Right[i][j]);
                    }
                }
            }
        }
        int ans = INF;
        for (int i = 0; i <= 2 * max(M,N); i++) {
            if (DP[M][N][i][0<= G)
                ans = min(ans, (M + N - 2* L + i);
            if (DP[M][N][i][1<= G)
                ans = min(ans, (M + N - 2* L + i);
        }
        if (ans == INF)
            cout << -1 << "\n";
        else cout << ans << "\n";
    }
    return 0;
}
 
cs

이 문제λ₯Ό ν’€λ©΄μ„œ μƒˆλ‘­κ²Œ μ•Œκ²Œλœ 정보가 μžˆλ‹€. memset을 ν•  λ•Œ λ¬΄ν•œμœΌλ‘œ μ΄ˆκΈ°ν™” ν•˜κ³ μ‹Άμ„λ•ŒλŠ” μ–΄λ–»κ²Œ ν•˜λ‚˜ κΆκΈˆν–ˆλŠ”λ° 보톡 0x3f 둜 μ΄ˆκΈ°ν™”λ₯Ό μ‹œν‚¨λ‹€κ³  ν•œλ‹€. λ¬Όλ‘  0x3f λ₯Ό 두 배해도 INT_MAXκ°’ λ³΄λ‹€λŠ” μž‘λ‹€κ³  ν•œλ‹€.

728x90