반응형

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

 

17779번: 게리맨더링 2

재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름

www.acmicpc.net

처음 접근법


: 5구역을 먼저 계산하고 1~4구역을 계산

 

① 5구역 계산하면서 visited 체크

② 1~4구역을 문제에서 주어진 수식대로 범위를 지정하여 계산.

    for문을 돌리면서 visited 처리가 된 것은 5구역에 포함되는 부분이므로, 각 구역 계산 시 포함시키지 않음

 

문제점

1~4구역 나누는 것은 문제에 주어진 수식을 참고하여 코드를 작성했지만,

5구역 나누는 법은 도무지 생각이 나지 않았다...

 

두 번째 접근법 (블로그 참고)


: 1~4구역을 먼저 계산하고 5구역을 계산

 

① 1~4구역 계산 시, if 문에서 5구역을 걸러내는 조건을 이용해서 5구역 필터링.

② 전체 영억 - (1~4구역) 으로 5구역 계산

 

문제점

5구역을 걸러내는 조건이 아주 까다로웠다...

그림을 그려봐도, 코드를 계속 읽어봐도 이해가 안됐다.

무엇보다 비슷한 유형의 문제를 풀 때, 이 방법대로 구현할 자신이 없었다.

 

세 번째 접근법 (유튜브 참고): https://youtu.be/fAs85oVcu1g


 

 

: 5구역의 경계를 설정하고, 1~4구역 계산 시 필터링

 

 

① 문제에서 주어진 5구역 경계 수식을 참고하여 5구역 경계 설정

② 1~4구역 계산 시 5구역의 경계를 만나면 다음 행으로 넘어감

 

해결

이 영상 보자마자 바로 방법을 깨달았다.

단순하게 5구역의 경계만 설정함으로써 간단하게 1~4구역을 계산할 수 있었다.

복잡하게 5구역을 먼저 계산할 필요도, 1~4구역 계산 시 5구역 필터링을 어렵게 할 필요도 없는 것이다.

5구역의 경계를 설정하는 수식은 아주 간단하다. 문제에 있는 조건을 그대로 이용하면 된다.

 

문제에서 주어진 5구역의 경계

5구역의 경계를 표시하는 소스코드

1
2
3
4
5
6
7
8
9
    // 5구역 경계 설정
    for (int i = 0; i <= d1; i++) {
        border[x + i][y - i] = 5;             // 5-1 경계 (x, y), (x+1, y-1), ..., (x+d1, y-d1)
        border[x + d2 + i][y + d2 - i] = 5;   // 5-4 경계 (x+d2, y+d2), (x+d2+1, y+d2-1), ..., (x+d2+d1, y+d2-d1)
    }
    for (int i = 0; i <= d2; i++) {
        border[x + i][y + i] = 5;             // 5-2 경계 (x, y), (x+1, y+1), ..., (x+d2, y+d2)
        border[x + d1 + i][y - d1 + i] = 5// 5-3 경계 (x+d1, y-d1), (x+d1+1, y-d1+1), ... (x+d1+d2, y-d1+d2)
    }
cs

 

1~4구역 계산도 마찬가지로 문제에 주어진 수식을 활용하여 쉽게 수행할 수 있다.

 

문제에서 주어진 1~4구역의 범위

1~4구역 계산하는 소스코드

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
    // 1번 선거구: 1 ≤ r < x+d1, 1 ≤ c ≤ y
    for (int i = 1; i < x+d1; i++) {
        for (int j = 1; j <= y; j++) {
            if (border[i][j] == 5break;
            area[1+= arr[i][j];
        }
    }
    // 2번 선거구 : 1 ≤ r ≤ x + d2, y < c ≤ N
    for (int i = 1; i <= x + d2; i++) {
        for (int j = n; j > y; j--) {
            if (border[i][j] == 5break;
            area[2+= arr[i][j];
        }
    }
    // 3번 선거구 : x + d1 ≤ r ≤ N, 1 ≤ c < y - d1 + d2
    for (int i = x+d1; i <= n; i++) {
        for (int j = 1; j < y-d1+d2; j++) {
            if (border[i][j] == 5break;
            area[3+= arr[i][j];
        }
    }
    // 4번 선거구 : x + d2 < r ≤ N, y - d1 + d2 ≤ c ≤ N
    for (int i = x + d2+1; i <= n; i++) {
        for (int j = n; j >= y-d1+d2; j--) {
            if (border[i][j] == 5break;
            area[4+= arr[i][j];
        }
    }
    // 5번 선거구
    area[5= total;
    rep(i, 4)
        area[5-= area[i];
cs

 

진행 과정

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <iostream>
#include <algorithm>
#include <cstring>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
int n, arr[21][21], area[6], border[21][21];
int max_val, min_val, ans = 1e9, total;
void input();
void init();
bool isValidArea(int x, int y, int d1, int d2);    // 범위 검사
void getArea(int x, int y, int d1, int d2);        // 범위 계산
 
// 1. (x, y), d1, d2 정하기
// 2. 구역 별 인구수 계산
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    input();
 
    for (int x = 1; x <= n;x++) {
        for (int y = 1; y <= n;y++) {
            for (int d1 = 1; d1 < n; d1++) {
                for (int d2 = 1;d2 < n;d2++) {
                    init();
                    if (isValidArea(x, y, d1, d2)) {
                        getArea(x, y, d1, d2);
                        ans = min(ans, max_val - min_val);
                    }
                }
            }
        }
    }
    cout << ans;
}
bool isValidArea(int x, int y, int d1, int d2) {
    if (x<1 || x>|| y<1 || y>n) return 0;    //    상: (x,y)
    if (x + d1 + d2<1 || x + d1 + d2>|| y - d1 + d2<1 || y - d1 + d2>n) return 0;    //    하: (x+d1+d2, y-d1+d2)
    if (x + d1<1 || x + d1>|| y - d1<1 || y - d1>n) return 0;    //    좌: (x+d1, y-d1)
    if (x + d2<1 || x + d2>|| y + d2<1 || y + d2>n) return 0;    //    우: (x+d2, y+d2)
    return 1;
}
// 범위 계산
void getArea(int x, int y, int d1, int d2) {
    // 5구역 경계 설정
    for (int i = 0; i <= d1; i++) {
        border[x + i][y - i] = 5;            // 5-1 경계 (x, y), (x+1, y-1), ..., (x+d1, y-d1)
        border[x + d2 + i][y + d2 - i] = 5;    // 5-4 경계 (x+d2, y+d2), (x+d2+1, y+d2-1), ..., (x+d2+d1, y+d2-d1)
    }
    for (int i = 0; i <= d2; i++) {
        border[x + i][y + i] = 5;            // 5-2 경계 (x, y), (x+1, y+1), ..., (x+d2, y+d2)
        border[x + d1 + i][y - d1 + i] = 5// 5-3 경계 (x+d1, y-d1), (x+d1+1, y-d1+1), ... (x+d1+d2, y-d1+d2)
    }
 
    // 1번 선거구: 1 ≤ r < x+d1, 1 ≤ c ≤ y
    for (int i = 1; i < x+d1; i++) {
        for (int j = 1; j <= y; j++) {
            if (border[i][j] == 5break;
            area[1+= arr[i][j];
        }
    }
    // 2번 선거구 : 1 ≤ r ≤ x + d2, y < c ≤ N
    for (int i = 1; i <= x + d2; i++) {
        for (int j = n; j > y; j--) {
            if (border[i][j] == 5break;
            area[2+= arr[i][j];
        }
    }
    // 3번 선거구 : x + d1 ≤ r ≤ N, 1 ≤ c < y - d1 + d2
    for (int i = x+d1; i <= n; i++) {
        for (int j = 1; j < y-d1+d2; j++) {
            if (border[i][j] == 5break;
            area[3+= arr[i][j];
        }
    }
    // 4번 선거구 : x + d2 < r ≤ N, y - d1 + d2 ≤ c ≤ N
    for (int i = x + d2+1; i <= n; i++) {
        for (int j = n; j >= y-d1+d2; j--) {
            if (border[i][j] == 5break;
            area[4+= arr[i][j];
        }
    }
    // 5번 선거구
    area[5= total;
    rep(i, 4)
        area[5-= area[i];
 
    rep(i, 5) {
        max_val = max(max_val, area[i]);
        min_val = min(min_val, area[i]);
    }
}
 
void input() {
    cin >> n;
    rep(i, n) {
        rep(j, n) {
            cin >> arr[i][j];
            total += arr[i][j];
        }
    }
}
void init() {
    memset(area, 0sizeof(area));
    memset(border, 0sizeof(border));
    max_val = -1;
    min_val = 1e9;
}
cs
반응형

'백준 > 삼성기출' 카테고리의 다른 글

백준 17837 [4%에서 틀렸습니다.]  (0) 2021.08.08
백준 17142  (0) 2021.08.04
백준 17143  (0) 2021.07.19
백준 5373 [복습필수]  (0) 2021.04.30
백준 16234  (0) 2021.04.30
반응형

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

 

17142번: 연구소 3

인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 바이러스는 활성 상태와 비활성 상태가 있다. 가장 처음에 모든 바이러스는 비활성 상태이고

www.acmicpc.net

1. 백트래킹으로 활성화 할 바이러스 선택

  - 2차원 배열에서 백트래킹하면 시간초과

  - arr[i][j] = 2인 {i, j} 값을 벡터에 저장시킨 뒤, 해당 벡터에 대해서 백트래킹 수행

 

2. m개 활성시켰으면 BFS로 시간 계산

  - arr[i][j]에서 BFS 수행하면 입력이 변경되므로, 다음 백트래킹 수행 시 계산 잘못됨

  - arr[i][j]가 아니라 copy_arr[i][j]에서 BFS 수행

 

0: 빈 칸

1: 벽

2: 바이러스 (비활성화)

3: 바이러스 (활성화)

 

소스코드

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
#include <vector>
#define rep(i,n) for(int i=0;i<n;i++)
#define pii pair<intint>
using namespace std;
queue<pii> q;
vector<pii> virus;
int n, m, arr[51][51], copy_arr[51][51], zero_cnt, ans = 1e9;
bool visited[51][51];
int dx[] = { -1010 };
int dy[] = { 010-1 };
void input();
void bfsInit() {
    memset(visited, 0sizeof(visited));
    while (!q.empty())
        q.pop();
    zero_cnt = 0;
    rep(i, n) {
        rep(j, n) {
            copy_arr[i][j] = arr[i][j];
            // 활성화된 바이러스를 queue에 삽입하고 방문처리
            if (copy_arr[i][j] == 3) {
                q.push({ i,j });
                visited[i][j] = 1;
            }
            // 빈 칸의 개수 체크
            else if (copy_arr[i][j] == 0) zero_cnt++;
        }
    }
}
// return 시간(초)
int bfs() {
    int cnt = 0;
    bfsInit();
    while (!q.empty()) {
        int size = q.size();
        // 빈 칸 없으면 종료
        if (zero_cnt == 0break;
        while (size--) {
            pii now = q.front(); q.pop();
            int x = now.first;
            int y = now.second;
            visited[x][y] = 1;
            rep(i, 4) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                if (nx < 0 || nx >= n || ny < 0 || ny >= n || visited[nx][ny]) continue;
                // 1: 벽이라서 멈춤
                if (copy_arr[nx][ny] == 1continue;
 
                // 0, 2: 활성화 상태(3)로 변경 후 전파시킴
                else if (copy_arr[nx][ny] == 0 || copy_arr[nx][ny]==2) {
                    if (copy_arr[nx][ny] == 0) zero_cnt--;
                    copy_arr[nx][ny] = 3;
                    visited[nx][ny] = 1;
                    q.push({ nx, ny });
                }
                
                // 3: 이미 visited라서 걸러질 것
            }
        }
        cnt++;
    }
    return cnt;
}
 
void backTrackking(int idx, int cnt) {
    // 바이러스를 m개 만큼 활성화 시켰으면 bfs 실행
    if (cnt == m) {
        int ret = bfs();
 
        // 빈 칸 개수가 0개일 때만 갱신
        if (zero_cnt == 0)
            ans = min(ans, ret);
        return;
    }
 
    // 백트래킹으로 활성화시킬 바이러스 찾기
    for (int i = idx; i < virus.size(); i++) {
        int x = virus[i].first;
        int y = virus[i].second;
        if (arr[x][y] == 2) {
            arr[x][y] = 3;
            backTrackking(i, cnt + 1);
            arr[x][y] = 2;
        }
    }
}
// 1. 활성화 시킬 바이러스 선택하기 (백트래킹)
// 2. 시간 얼마나 걸리는지 계산하기 (bfs)
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    input();
    backTrackking(00);
    cout << (ans==1e9?-1:ans);
}
 
void input() {
    cin >> n >> m;
    rep(i, n) {
        rep(j, n) {
            cin >> arr[i][j];
            if (arr[i][j] == 2)
                virus.push_back({ i,j });
        }
    }
}
cs

 

반응형

'백준 > 삼성기출' 카테고리의 다른 글

백준 17837 [4%에서 틀렸습니다.]  (0) 2021.08.08
백준 17779 [복습 필수]  (0) 2021.08.06
백준 17143  (0) 2021.07.19
백준 5373 [복습필수]  (0) 2021.04.30
백준 16234  (0) 2021.04.30
반응형

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

 

9470번: Strahler 순서

지질학에서 하천계는 유향그래프로 나타낼 수 있다. 강은 간선으로 나타내며, 물이 흐르는 방향이 간선의 방향이 된다. 노드는 호수나 샘처럼 강이 시작하는 곳, 강이 합쳐지거나 나누어지는 곳

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
vector<vector<int> > v;
queue<int> q;
struct Node {
    int val;    // 들어오는 순서 중 최댓값
    bool dup;    // val의 중복 여부
};
int in_degree[1001], order[1001];
Node temp[1001];
int t, k, m, p, a, b;
void input();
void findZeroIndegree();
void topologySort() {
    while (!q.empty()) {
        int now = q.front(); q.pop();
        for (int next : v[now]) {
            // 들어오는 값 중에서 최댓값 찾기
            // 1. 중복 (X)
            if (order[now] > temp[next].val) {
                temp[next].val = order[now];
                temp[next].dup = 0;
            }
            // 2. 중복 (O)
            else if (order[now] == temp[next].val) 
                temp[next].dup = 1;
            
            if (--in_degree[next] == 0) {
                // 들어오는 값 더 없으면 순서 갱신
                order[next] = temp[next].val + (temp[next].dup ? 1 : 0);
                q.push(next);
            }
        }
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> t;
    while (t--) {
        input();
        findZeroIndegree();
        topologySort();
        cout << k << ' ' << order[m] << '\n';
    }
}
void input() {
    cin >> k >> m >> p;
    v.clear();
    v.resize(m + 1);
    memset(temp, 0sizeof(temp));
    memset(order, 0sizeof(order));
    memset(in_degree, 0sizeof(in_degree));
    rep(i, p) {
        cin >> a >> b;
        v[a].push_back(b);
        in_degree[b]++;
    }
}
void findZeroIndegree() {
    rep(i, m) {
        if (in_degree[i] == 0) {
            q.push(i);
            order[i] = 1;
        }
    }
}
cs
반응형

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

백준 1197  (0) 2021.07.12
백준 1922  (0) 2021.07.12
백준 2252  (0) 2021.07.12
반응형

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

 

2213번: 트리의 독립집합

첫째 줄에 트리의 정점의 수 n이 주어진다. n은 10,000이하인 양의 정수이다. 1부터 n사이의 정수가 트리의 정점이라고 가정한다. 둘째 줄에는 n개의 정수 w1, w2, ..., wn이 주어지는데, wi는 정점 i의

www.acmicpc.net

1. 최댓값 찾기

012345

2. 출력

01234

소스코드 

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#define rep(i,n) for(int i=1;i<=n;i++)
#define pii pair<intint>
 
using namespace std;
vector<vector<int> > v;
vector<pii> child[10001][2];
priority_queue<int> pq;
int n, dp[10001][2], a,b;
bool visited[10001];
void input();
void print();
void dfs(int now) {
    for (int next : v[now]) {
        if (!visited[next]) {
            visited[next] = 1;
            dfs(next);
 
            // now 미포함
            if (dp[next][0> dp[next][1]) {
                dp[now][0+= dp[next][0];
                child[now][0].push_back({ next,0 });
            }
            else {
                dp[now][0+= dp[next][1];
                child[now][0].push_back({ next,1 });
            }
 
            // now 포함
            dp[now][1+= dp[next][0];
            child[now][1].push_back({ next, 0 });
        }
    }
}
 
void trace(int now, int idx) {
    if (idx == 1)
        pq.push(-now);
    for (pii next : child[now][idx]) 
        trace(next.first, next.second);
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    input();
    visited[1= 1;
    dfs(1);
 
    if (dp[1][0> dp[1][1]) trace(10);
    else trace(11);
 
    print();
}
 
void input() {
    cin >> n;
    v.resize(n + 1);
    rep(i, n)
        cin >> dp[i][1];
    rep(i, n - 1) {
        cin >> a >> b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
}
void print() {
    cout << max(dp[1][0], dp[1][1]) << '\n';
    while (!pq.empty()) {
        cout << -pq.top() << ' ';
        pq.pop();
    }
}
cs
반응형

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

백준 2533 [복습필수]  (0) 2021.08.01
백준 15681  (0) 2021.07.30
백준 1005  (0) 2021.07.24
반응형

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

 

2533번: 사회망 서비스(SNS)

페이스북, 트위터, 카카오톡과 같은 사회망 서비스(SNS)가 널리 사용됨에 따라, 사회망을 통하여 사람들이 어떻게 새로운 아이디어를 받아들이게 되는가를 이해하는 문제가 중요해졌다. 사회망

www.acmicpc.net

DP

dp[i][0]: 본인이 얼리어답터가 아님 -> 이웃 모두 얼리어답터
dp[i][1]: 본인이 얼리어답터임        -> 이웃 얼리어답터 상관 없이 작은 값 

 

점화식

dp[now][0] += dp[next][1]

dp[now][1] += min(dp[next][0], dp[next][1])

 

간선 양방향 및 visited 쓰는 이유

간선 단방향으로 입력할 경우, 간선 a, b 순서가 바뀌면 값이 달라짐

8

1 2

1 3

1 4

2 5

2 6

4 7

4 8

 

8
2 1
3 1
4 1
5 2
6 2
7 4
8 4

진행과정

0123456

소스 코드

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>
#include <cstring>
#include <vector>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
vector<vector<int> > v;
int n, a, b, visited[1000001];
int dp[1000001][2];    // dp[i][0]: 본인이 얼리어답터가 아님    -> 이웃 모두 얼리어답터
                    // dp[i][1]: 본인이 얼리어답터임        -> 얼리어답터 상관없음
void func(int now) {
    dp[now][1= 1;
    for (int next : v[now]) {
        if (!visited[next]) {
            visited[next] = 1;
            func(next);
            dp[now][0+= dp[next][1];
            dp[now][1+= min(dp[next][0], dp[next][1]);
        }
    }
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    v.resize(n + 1);
    rep(i, n-1) {
        cin >> a >> b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
    visited[1= 1;
    func(1);
    cout << min(dp[1][0], dp[1][1]);
}
cs
반응형

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

백준 2213  (0) 2021.08.02
백준 15681  (0) 2021.07.30
백준 1005  (0) 2021.07.24
반응형

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

 

15681번: 트리와 쿼리

트리의 정점의 수 N과 루트의 번호 R, 쿼리의 수 Q가 주어진다. (2 ≤ N ≤ 105, 1 ≤ R ≤ N, 1 ≤ Q ≤ 105) 이어 N-1줄에 걸쳐, U V의 형태로 트리에 속한 간선의 정보가 주어진다. (1 ≤ U, V ≤ N, U ≠ V)

www.acmicpc.net

DFS로 간단하게 해결 가능

 

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
#include <iostream>
#include <vector>
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
vector<vector<int> > v;
int n, r, q, a, b,x, child[100001], visited[100001];
void input();
void print();
int func(int r) {
    for (int next : v[r]) {
        if (!visited[next]) {
            visited[next] = 1;
            child[r]+=func(next);
        }
    }
    return child[r] + 1;
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    input();
    func(r);
    print();
}
void input() {
    cin >> n >> r >> q;
    v.resize(n + 1);
    rep(i, n - 1) {
        cin >> a >> b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
    visited[r] = 1;
}
void print() {
    rep(i, q) {
        cin >> x;
        cout << child[x] + 1 << '\n';
    }
}
cs
반응형

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

백준 2213  (0) 2021.08.02
백준 2533 [복습필수]  (0) 2021.08.01
백준 1005  (0) 2021.07.24
반응형

 

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
반응형

스프링 핵심 원리 - 기본편 - 인프런 | 강의 (inflearn.com)

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

EJB 어렵고 복잡하고 느림

  -> POJO, 옛날로 돌아감

  -> 스프링 (EJB 문제점 지적),

  -> 하이버네이트 (EJB 엔티티 빈 기술 대체) -> JPA (자바 표준)

  => 스프링: 전통적인 J2EE (EJB)라는 겨울을 넘어 새로운 시작

 

스프링부트

tomcat 내장 -> 별도의 웹 서버 설치 안해도 됨

라이브러리 버전 맞춰줌

 

스프링 -> 자바 기반 -> "객체 지향"

객체 지향 언어가 가진 강력한 특징을 살려내는 프레임워크

좋은 객체 지향 앱을 개발할 수 있게 도와주는 프레임워크

 

 

좋은 객체 지향 프로그래밍

  • 추상화, 캡슐화, 상속, 다형성
  • 여러 개의 독립된 단위, "객체들의 모임". 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.
  • 프로그램을 유연하고 변경 용이하도록
  • "갈아 끼우기" => "다형성"
  • 자동차가 바껴도 운전자에게 영향을 주지 않음 (자동차 역할 / 자동차 구현 / 운전자 역할 구분)
  • 클라이언트에 영향을 끼치지 않고 새로운 기능 제공

 

역할 / 구현 나눠서 구현

  - 로미오 역할: 장동건, 원빈

  - 줄리엣 역할: 김태희, 송혜교

다른 대상 (배우)으로 변경 가능 -> 유연하고 변경 용이

 

클라이언트

  - 대상의 역할(인터페이스)만 알면 됨

  - 구현 대상의 내부 구조 몰라도 됨

  - 구현 대상의 내부 구조가 변경되어도 영향을 받지 않음.

  - 구현 대상 자체를 변경해도 영향을 받지 않음

 

자바

  - 역할: 인터페이스

  - 구현: 인터페이스를 구현한 클래스, 구현 객체

 

객체 설계 시 역할(인터페이스) 먼저 부여하고, 그것을 수행하는 구현 객체 만들기

 

다형성

인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경 가능

클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.

 

MemberRepository 인터페이스의 구현체를 MemoryMemberRepository, JdbcMemberRepository로 갈아끼울 수 있음

 

역할(인터페이스) 자체가 변하면 클라이언트, 서버 모두 변경

인터페이스를 안정적으로 잘 설계하는 것이 중요

 

스프링=>다형성

IoC (제어 역전), DI (의존관계 주입)은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원

반응형

+ Recent posts