반응형

 

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

 

9252번: LCS 2

LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.

www.acmicpc.net

 

1. LCS 길이 계산

https://youtu.be/CvUPYVGXIrE

2. LCS 찾기

01234567

 

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
#include <iostream>
#include <algorithm>
#include <stack>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
string a, b;
stack<char> s;
int dp[1002][1002];
void lcs_length() {
    rep(i, b.length()) {
        rep(j, a.length()) {
            if (b[i - 1== a[j - 1]) dp[i][j] = dp[i - 1][j - 1+ 1;
            else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        }
    }
    int len = dp[b.length()][a.length()];
    cout << len << '\n';
}
void lcs_find() {
    int i = b.length();
    int j = a.length();
    while (dp[i][j] > 0) {
        if (b[i - 1== a[j - 1]) {
            s.push(b[i - 1]);
            i--, j--;
        }
        else {
            if (dp[i - 1][j] > dp[i][j - 1]) i--;
            else j--;
        }
    }
 
    while (!s.empty()) {
        cout << s.top();
        s.pop();
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> a >> b;
    lcs_length();
    lcs_find();
}
cs
반응형

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

백준 1915 [복습필수]  (0) 2021.07.28
백준 11066  (0) 2021.07.27
백준 1937  (0) 2021.07.26
백준 1890  (0) 2021.07.23
백준 2293  (0) 2021.07.20
반응형

 

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

 

1915번: 가장 큰 정사각형

첫째 줄에 n, m(1 ≤ n, m ≤ 1,000)이 주어진다. 다음 n개의 줄에는 m개의 숫자로 배열이 주어진다.

www.acmicpc.net

 

처음 접근법 (실패)

DFS (재귀) 이용

DFS 호출할 때마다 cnt 증가 (cnt: 정사각형 한 변의 길이를 의미)

오른쪽, 아래쪽, 오른쪽 아래 대각선이 모두 1이면 dp[i][j] = cnt

하나라도 0이거나 범위를 벗어나면 탐색 불가 (return 0 또는 cnt-1)

 

두 번째 접근법 (https://yabmoons.tistory.com/158)

위 블로그 설명에서는 왼쪽, 위쪽, 왼쪽 위 대각선을 탐색했는데,

나는 오른쪽, 아래쪽, 오른쪽 아래 대각선을 탐색해도 될 거라고 판단

하지만, 내가 생각한 방법대로 하면 한 번 계산한 행 (또는 열)은 다음 계산에 반영 안됨.

블로그 설명대로 왼쪽, 위쪽, 왼쪽 위 대각선을 탐색한다면 한 번 계산한 행 (또는 열)도 다음 계산에 반영됨.

 

진행과정

012345678

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
#include <iostream>
#include <algorithm>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
int n, m, dp[1001][1001], ans;
void input();
void func() {
    rep(i, n) {
        rep(j, m) {
            if (dp[i][j] == 1)
                dp[i][j] = min(dp[i][j - 1], min(dp[i - 1][j - 1], dp[i - 1][j])) + 1;
            ans = max(ans, dp[i][j]);
        }
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    input();
    func();
    cout << ans * ans;
}
void input() {
    cin >> n >> m;
    rep(i, n) {
        rep(j, m) {
            char c;
            cin >> c;
            dp[i][j]= c - '0';
        }
    }
}
cs
반응형

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

백준 9252 [복습필수]  (0) 2021.07.29
백준 11066  (0) 2021.07.27
백준 1937  (0) 2021.07.26
백준 1890  (0) 2021.07.23
백준 2293  (0) 2021.07.20
반응형

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

 

11066번: 파일 합치기

소설가인 김대전은 소설을 여러 장(chapter)으로 나누어 쓰는데, 각 장은 각각 다른 파일에 저장하곤 한다. 소설의 모든 장을 쓰고 나서는 각 장이 쓰여진 파일을 합쳐서 최종적으로 소설의 완성본

www.acmicpc.net

0123

 

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
#include <iostream>
#include <cstring>
#include <algorithm>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
int t, n, dp[501][501], sum[501];
void input();
void func() {
    int total_diff = n - 1;
 
    rep(diff, total_diff) {
        rep(i, n-diff) {
            int j = i + diff;
            for (int k = i; k < j; k++) {
                int temp = dp[i][k] + dp[k + 1][j] + sum[j]-sum[i-1];
                if (dp[i][j] == 0 || temp < dp[i][j])
                    dp[i][j] = temp;
            }
        }
    }
 
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> t;
 
    while (t--) {
        input();
        func();
        cout << dp[1][n]<<'\n';
    }
}
 
void input() {
    memset(dp, 0sizeof(dp));
    cin >> n;
    rep(i, n) {
        cin >> sum[i];
        sum[i] += sum[i - 1];
    }
}
cs
반응형

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

백준 9252 [복습필수]  (0) 2021.07.29
백준 1915 [복습필수]  (0) 2021.07.28
백준 1937  (0) 2021.07.26
백준 1890  (0) 2021.07.23
백준 2293  (0) 2021.07.20
반응형

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

 

1937번: 욕심쟁이 판다

n × n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에

www.acmicpc.net

dp[i][j]

i, j에서 갈 수 있는 최대 개수

 

DFS 핵심

현재 칸에서 다음 칸으로 이동: 1번

다음 칸에서 임의의 칸으로 이동: 최대 x번

∴ 현재 칸 -> 다음 칸 -> 임의의 칸: 최대 x + 1번

 

다음 칸의 계산이 이미 끝났을 경우 (visited = true)

  -> 다음 칸의 값(dp[nx][ny])을 가져와서 계산

 

다음 칸의 계산이 안되어 있을 경우 (visited = false)

  -> dfs(nx, ny) 수행 / return 값: 다음 칸의 값

1
2
3
4
5
6
7
// 계산이 끝났을 경우
if (visited[nx][ny])
    dp[x][y] = max(dp[x][y], dp[nx][ny] + 1);
 
// 계산을 해야하는 경우
else 
    dp[x][y] = max(dp[x][y], dfs(nx, ny) + 1);
cs

 

진행과정

012345678910

소스코드

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
51
#include <iostream>
#include <algorithm>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
int dx[] = { -1010 };
int dy[] = { 010-1 };
int ans, n, arr[501][501], dp[501][501];
bool visited[501][501];
// dp[i][j]: i, j에서 갈 수 있는 최대 개수
int dfs(int x, int y) {
    visited[x][y] = 1;
    dp[x][y]++;
    rep(i, 4) {
        int nx = x + dx[i];
        int ny = y + dy[i];
 
        // 이동 불가
        if (nx < 0 || ny >= n || ny < 0 || ny >= n || arr[x][y] >= arr[nx][ny]) continue;
 
        // 계산이 끝났을 경우
        if (visited[nx][ny])
            dp[x][y] = max(dp[x][y], dp[nx][ny] + 1);
 
        // 계산을 해야하는 경우
        else 
            dp[x][y] = max(dp[x][y], dfs(nx, ny) + 1);
    }
    return dp[x][y];
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    rep(i, n) {
        rep(j, n) 
            cin >> arr[i][j];
    }
 
    rep(i, n) {
        rep(j, n) {
            if (!visited[i][j]) 
                dfs(i, j);
        }
    }
 
    rep(i, n) {
        rep(j, n)
            ans = max(ans, dp[i][j]);
    }
    cout << ans;
}
cs
반응형

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

백준 1915 [복습필수]  (0) 2021.07.28
백준 11066  (0) 2021.07.27
백준 1890  (0) 2021.07.23
백준 2293  (0) 2021.07.20
백준 1103  (0) 2021.07.08
반응형

 

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

 

1890번: 점프

첫째 줄에 게임 판의 크기 N (4 ≤ N ≤ 100)이 주어진다. 그 다음 N개 줄에는 각 칸에 적혀져 있는 수가 N개씩 주어진다. 칸에 적혀있는 수는 0보다 크거나 같고, 9보다 작거나 같은 정수이며, 가장

www.acmicpc.net

DP 써야하는 이유

Priority Queue 사용한 이유

(1, 2)가 3이 된 상태에서 (1, 3)과 (2, 2)를 업데이트 해야 하는데

(1, 2)가 1일 때 (1, 3)과 (2, 2)를 업데이트 한 뒤에 (1, 2)가 3이 되면 값이 이상해진다.

 

반례

4

1 1 1 1

2 1 1 1

1 1 1 1

1 1 1 0

 

 

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
51
52
#include <iostream>
#include <queue>
#define rep(i,n) for(int i=0;i<n;i++)
#define ll long long
using namespace std;
struct Node {
    int x;
    int y;
};
struct cmp {
    bool operator()(Node a, Node b) {
        return a.x + a.y > b.x + b.y;
    }
};
int n, arr[101][101];
int dx[] = { 10 };
int dy[] = { 01 };
bool visited[101][101];
ll dp[101][101];
void func() {
    priority_queue<Node, vector<Node>, cmp> q;
    q.push({ 0,0 });
    dp[0][0= 1;
    visited[0][0= 1;
    while (!q.empty()) {
        Node now = q.top(); q.pop();
        int x = now.x;
        int y = now.y;
        if (arr[x][y] == 0continue;
        rep(i, 2) {
            int nx = x + dx[i] * arr[x][y];
            int ny = y + dy[i] * arr[x][y];
            if (nx >= n || ny >= n) continue;
            if (!visited[nx][ny]) {
                visited[nx][ny] = 1;
                q.push({ nx, ny });
            }
            dp[nx][ny] += dp[x][y];
        }
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    rep(i, n) {
        rep(j, n)
            cin >> arr[i][j];
    }
    func();
    cout << dp[n - 1][n - 1];
}
cs
반응형

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

백준 11066  (0) 2021.07.27
백준 1937  (0) 2021.07.26
백준 2293  (0) 2021.07.20
백준 1103  (0) 2021.07.08
백준 11054  (0) 2021.02.19
반응형

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

 

2293번: 동전 1

첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다.

www.acmicpc.net

0123

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
int n, k, arr[101], dp[10001];
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n >> k;
    rep(i, n) 
        cin >> arr[i];
 
    rep(i, n) {
        int coin = arr[i];
        rep(value, k) {
            if (value == coin)
                dp[value]++;
            if (value < coin) continue;
            dp[value] = dp[value] + dp[value - coin];
        }
    }
    cout << dp[k];
 
}
cs
반응형

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

백준 1937  (0) 2021.07.26
백준 1890  (0) 2021.07.23
백준 1103  (0) 2021.07.08
백준 11054  (0) 2021.02.19
백준 13398 [복습 필수]  (0) 2021.02.18
반응형

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

 

1103번: 게임

줄에 보드의 세로 크기 N과 가로 크기 M이 주어진다. 이 값은 모두 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 보드의 상태가 주어진다. 쓰여 있는 숫자는 1부터 9까지의 자연수 또는

www.acmicpc.net

dfs + dp 문제

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
#include <iostream>
#include <algorithm>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
int n, m, arr[51][51], ans;
int dx[] = { -1010 };
int dy[] = { 010-1 };
int visited[51][51];
void input();
void dfs(int x, int y, int cnt) {
    // 무한번 이동가능
    if (cnt > n*m) {
        cout << -1;
        exit(0);
    }
 
    // dp 체크
    if (cnt <= visited[x][y]) return;
 
    // 방문 처리
    ans = max(ans, cnt);
    visited[x][y] = cnt;
    rep(i, 4) {
        int nx = x + dx[i]*arr[x][y];
        int ny = y + dy[i]*arr[x][y];
        if (nx < 0 || nx >= n || ny < 0 || ny >= m || arr[nx][ny] == -1continue;
        dfs(nx, ny, cnt+1);
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    input();
    dfs(001);
    cout << ans;
}
 
void input() {
    cin >> n >> m;
    rep(i, n) {
        rep(j, m) {
            char c;
            cin >> c;
            if (c == 'H') arr[i][j] = -1;
            else arr[i][j] = c - '0';
        }
    }
}
cs
반응형

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

백준 1890  (0) 2021.07.23
백준 2293  (0) 2021.07.20
백준 11054  (0) 2021.02.19
백준 13398 [복습 필수]  (0) 2021.02.18
백준 2133 [복습 필수] (점화식)  (0) 2021.02.17
반응형

www.acmicpc.net/problem/11054

 

11054번: 가장 긴 바이토닉 부분 수열

첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)

www.acmicpc.net

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
#include <iostream>
#include <algorithm>
using namespace std;
int n, ans, arr[1001], dp[1001], dp_rev[1001];
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> arr[i];
        dp[i] = dp_rev[i] = 1;
    }
 
    // 1. 증가하는 수열 찾기
    for (int i = 2; i <= n; i++) {
        for (int j = 1; j < i; j++) {
            if (arr[i] > arr[j])
                dp[i] = max(dp[i], dp[j] + 1);
        }
    }
 
    // 2. 역순으로 증가하는 수열 찾기 (감소하는 수열 찾기 -> 틀림!!)
    for (int i = n - 1; i >= 0; i--) {
        for (int j = n; j > i; j--) {
            if (arr[i] > arr[j])
                dp_rev[i] = max(dp_rev[i], dp_rev[j] + 1);
        }
    }
 
    // 3. 두개 더함
    for (int i = 1; i <= n; i++) {
        dp[i] += dp_rev[i];
        ans = max(ans, dp[i]);
    }
    cout << ans - 1;
}
cs
반응형

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

백준 2293  (0) 2021.07.20
백준 1103  (0) 2021.07.08
백준 13398 [복습 필수]  (0) 2021.02.18
백준 2133 [복습 필수] (점화식)  (0) 2021.02.17
백준 11055  (0) 2021.02.17

+ Recent posts