www.acmicpc.net/problem/17406

 

17406번: 배열 돌리기 4

크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의

www.acmicpc.net

앞의 배열 돌리기1, 2와 같이 배열이 주어지고 이 문제는 회전시킬 구간이 추가로 주어집니다.

구간은 r c s 이렇게 들어오는데 구간 (r - s, c - s) ~ (r + s, c + s)를 1번 회전시켜라는 뜻입니다.

하지만 이 연산 순서를 임의로 정해서 배열 A의 값을 최소로 해야하는 문제입니다.

즉, 구간정보를 브루트포스방식을 사용하여 모든 순서로 연산을 다 해봐야합니다.

 

연산 순서는 ArrayList를 활용하여 구간을 넣었다 뺐다 하는 방식으로 정하였고, 순서를 모두 정하면 list의 값을 복사한 다른 배열을 선언하여 모든 회전을 수행한 후에 A의 최솟값을 구하였습니다.

 

회전 로직은 1번, 2번과 같지만 구간에 해당하는 숫자가 1개인 경우 next로 자신으로 설정하는 예외처리를 해주었습니다.

 

 

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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int direct[][] = { { 10 }, { 01 }, { -10 }, { 0-1 } };
    static ArrayList<int[]> rotate = new ArrayList<>();
    static ArrayList<int[]> rotatesolve = new ArrayList<>();
    static boolean visit[][], chk[];
    static int list[][], clist[][];
    static int N, M, K, r, c, s;
    static int sx, sy, ex, ey, ans = Integer.MAX_VALUE;
 
    static void print() {
        System.out.println(ans);
    }
 
    static int dfs(int x, int y, int idx) {
        visit[x][y] = true;
 
        int nx = x + direct[idx][0];
        int ny = y + direct[idx][1];
 
        if (nx < sx || ny < sy || nx > ex || ny > ey) {
            idx++;
            nx = x + direct[idx][0];
            ny = y + direct[idx][1];
            if (nx < sx || ny < sy || nx > ex || ny > ey) {
                nx = x;
                ny = y;
            }
        }
 
        if (visit[nx][ny]) {
            int tmp = clist[x][y];
            clist[x][y] = clist[nx][ny];
            return tmp;
        }
 
        int tmp = clist[x][y];
        clist[x][y] = dfs(nx, ny, idx);
        return tmp;
    }
 
    static void solve(int rr, int cc, int ss) {
        sx = rr - ss;
        sy = cc - ss;
        ex = rr + ss;
        ey = cc + ss;
 
        for (int i = 0;; i++) {
            dfs(sx, sy, 0);
            sx++;
            sy++;
            ex--;
            ey--;
            if (sx > ex || sy > ey)
                break;
        }
 
        for (int i = rr - ss; i <= rr + ss; i++) {
            Arrays.fill(visit[i], false);
        }
    }
 
    static void func(int cnt) {
        if (cnt == K) {
            for (int i = 1; i <= N; i++) {
                for (int j = 1; j <= M; j++)
                    clist[i][j] = list[i][j];
            }
            for (int i = 0; i < K; i++) {
                solve(rotatesolve.get(i)[0], rotatesolve.get(i)[1], rotatesolve.get(i)[2]);
            }
 
            for (int i = 1; i <= N; i++) {
                int sum = 0;
                for (int j = 1; j <= M; j++) {
                    sum += clist[i][j];
                }
                ans = Math.min(ans, sum);
            }
 
            return;
        }
 
        for (int i = 0; i < K; i++) {
            if (chk[i])
                continue;
 
            rotatesolve.add(rotate.get(i));
            chk[i] = true;
            func(cnt + 1);
            chk[i] = false;
            rotatesolve.remove(cnt);
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        list = new int[N + 1][M + 1];
        clist = new int[N + 1][M + 1];
        visit = new boolean[N + 1][M + 1];
 
        for (int i = 1; i <= N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 1; j <= M; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
            }
        }
 
        for (int i = 0; i < K; i++) {
            st = new StringTokenizer(br.readLine());
            r = Integer.parseInt(st.nextToken());
            c = Integer.parseInt(st.nextToken());
            s = Integer.parseInt(st.nextToken());
            rotate.add(new int[] { r, c, s });
        }
 
        chk = new boolean[K];
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func(0);
        print();
    }
}
cs

'algorithm > dfs' 카테고리의 다른 글

boj 1987 알파벳  (0) 2021.02.18
boj 3109 빵집  (0) 2021.02.18
boj 16927 배열 돌리기 2  (0) 2021.02.10
boj 16926 배열 돌리기 1  (0) 2021.02.10
boj 1068 트리  (0) 2021.02.09

www.acmicpc.net/problem/16935

 

16935번: 배열 돌리기 3

크기가 N×M인 배열이 있을 때, 배열에 연산을 R번 적용하려고 한다. 연산은 총 6가지가 있다. 1번 연산은 배열을 상하 반전시키는 연산이다. 1 6 2 9 8 4 → 4 2 9 3 1 8 7 2 6 9 8 2 → 9 2 3 6 1 5 1 8 3 4 2 9 →

www.acmicpc.net

1. 배열을 상하반전 시킨다.

2. 배열을 좌우반전 시킨다.

3. 배열을 오른쪽으로 90도 회전시킨다.

4. 배열을 왼쪽으로 90도 회전시킨다.

5. 1번그룹 -> 2번그룹 / 2번그룹 -> 3번그룹 / 3번그룹 -> 4번그룹 / 4번그룹 -> 1번그룹으로 각각 이동시킨다.

6. 1번그룹 -> 4번그룹 / 4번그룹 -> 3번그룹 / 3번그룹 -> 2번그룹 / 2번그룹 -> 1번그룹으로 각각 이동시킨다.

 

1, 2번은 양끝의 숫자를 바꿔주기만 하면 됩니다.

3, 4번은 (N, M)크기의 배열을 회전시키면 (M, N)크기의 배열로 바뀝니다. 인덱스를 조절하여 해결합니다.

 

5, 6번은 위의 그림처럼 구간을

1번 - (0, 0) ~ (N / 2 - 1, M / 2 - 1)

2번 - (0, N / 2) ~ (N / 2 - 1, M - 1)

3번 - (N / 2, M / 2) ~ (N - 1, M - 1)

4번 - (N / 2, 0) ~ (N - 1, M / 2 - 1)

이렇게 나눠줍니다.

이제 인덱스를 조절해가며 이동시켜주시면 됩니다.

 

 

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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int list[][], calc[];
    static int N, M, R;
 
    static void cal1() {
        for (int i = 0, k = N - 1; i < N / 2; i++, k--) {
            for (int j = 0; j < M; j++) {
                int tmp = list[i][j];
                list[i][j] = list[k][j];
                list[k][j] = tmp;
            }
        }
    }
 
    static void cal2() {
        for (int i = 0; i < N; i++) {
            for (int j = 0, k = M - 1; j < M / 2; j++, k--) {
                int tmp = list[i][j];
                list[i][j] = list[i][k];
                list[i][k] = tmp;
            }
        }
    }
 
    static void cal3() {
        int newlist[][] = new int[M][N];
        int x = 0;
        int y = N - 1;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                newlist[x][y] = list[i][j];
                x++;
            }
            x = 0;
            y--;
        }
        int tmp = N;
        N = M;
        M = tmp;
 
        list = newlist;
    }
 
    static void cal4() {
        int newlist[][] = new int[M][N];
        int x = M - 1;
        int y = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                newlist[x][y] = list[i][j];
                x--;
            }
            x = M - 1;
            y++;
        }
        int tmp = N;
        N = M;
        M = tmp;
 
        list = newlist;
    }
 
    static void cal5() {
        int x1 = 0, y1 = 0;
        int x2 = 0, y2 = M / 2;
        int x3 = N / 2, y3 = M / 2;
        int x4 = N / 2, y4 = 0;
        for (int i = 0; i < N / 2; i++) {
            for (int j = 0; j < M / 2; j++) {
                int tmp = list[x1][y1];
                list[x1][y1] = list[x4][y4];
                list[x4][y4] = list[x3][y3];
                list[x3][y3] = list[x2][y2];
                list[x2][y2] = tmp;
 
                y1++;
                y2++;
                y3++;
                y4++;
            }
            y1 = 0;
            y2 = M / 2;
            y3 = M / 2;
            y4 = 0;
            x1++;
            x2++;
            x3++;
            x4++;
        }
    }
 
    static void cal6() {
        int x1 = 0, y1 = 0;
        int x2 = 0, y2 = M / 2;
        int x3 = N / 2, y3 = M / 2;
        int x4 = N / 2, y4 = 0;
        for (int i = 0; i < N / 2; i++) {
            for (int j = 0; j < M / 2; j++) {
                int tmp = list[x1][y1];
                list[x1][y1] = list[x2][y2];
                list[x2][y2] = list[x3][y3];
                list[x3][y3] = list[x4][y4];
                list[x4][y4] = tmp;
 
                y1++;
                y2++;
                y3++;
                y4++;
            }
            y1 = 0;
            y2 = M / 2;
            y3 = M / 2;
            y4 = 0;
            x1++;
            x2++;
            x3++;
            x4++;
        }
    }
 
    static void func() {
        for (int i = 0; i < R; i++) {
            if (calc[i] == 1)
                cal1();
            else if (calc[i] == 2)
                cal2();
            else if (calc[i] == 3)
                cal3();
            else if (calc[i] == 4)
                cal4();
            else if (calc[i] == 5)
                cal5();
            else
                cal6();
        }
    }
 
    static void print() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                sb.append(list[i][j] + " ");
            }
            sb.append("\n");
        }
 
        System.out.println(sb.toString());
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        R = Integer.parseInt(st.nextToken());
        list = new int[N][M];
        calc = new int[R];
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
            }
        }
 
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < R; i++) {
            calc[i] = Integer.parseInt(st.nextToken());
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
        print();
    }
}
cs

'algorithm > Implementation' 카테고리의 다른 글

boj 10157 자리배정  (0) 2021.02.17
boj 16918 봄버맨  (0) 2021.02.17
boj 1914 하노이 탑  (0) 2021.02.07
boj 11729 하노이 탑 이동 순서  (0) 2021.02.07
boj 1244 스위치 켜고 끄기  (0) 2021.02.01

www.acmicpc.net/problem/16927

 

16927번: 배열 돌리기 2

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5] ↓ ↑ A[2][1] A[2][2] ← A[2][3] ← A[2][4] A[2][5]

www.acmicpc.net

 

emoney96.tistory.com/110

 

boj 16926 배열 돌리기 1

www.acmicpc.net/problem/16926 16926번: 배열 돌리기 1 크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ←..

emoney96.tistory.com

위의 문제풀이와 동일합니다.

 

이 문제는 많은 회전으로 인한 TLE가 발생할 수 있는 문제였지만 저는 이전문제에서 이미 해줬던 부분이라 바로 AC를 받았습니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int visit[][];
    static int list[][];
    static int N, M, R;
    static int sx, sy, ex, ey;
 
    static void print() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                sb.append(list[i][j] + " ");
            }
            sb.append("\n");
        }
 
        System.out.println(sb.toString());
    }
 
    static int dfs(int x, int y, int idx) {
        visit[x][y]++;
 
        int nx = x + direct[idx][0];
        int ny = y + direct[idx][1];
 
        if (nx < sx || ny < sy || nx > ex || ny > ey) {
            idx++;
            nx = x + direct[idx][0];
            ny = y + direct[idx][1];
        }
 
        if (visit[nx][ny] == visit[x][y]) {
            int tmp = list[x][y];
            list[x][y] = list[nx][ny];
            return tmp;
        }
 
        int tmp = list[x][y];
        list[x][y] = dfs(nx, ny, idx);
        return tmp;
    }
 
    static void solve() {
        sx = 0;
        sy = 0;
        ex = N - 1;
        ey = M - 1;
        int n = N;
        int m = M;
        for (int i = 0;; i++) {
            for (int j = 0; j < R % ((n - 1* 2 + (m - 1* 2); j++) {
                dfs(i, i, 0);
            }
            sx++;
            sy++;
            ex--;
            ey--;
            n -= 2;
            m -= 2;
            if (sx > ex || sy > ey)
                break;
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        R = Integer.parseInt(st.nextToken());
        list = new int[N][M];
        visit = new int[N][M];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        solve();
        print();
    }
}
cs

'algorithm > dfs' 카테고리의 다른 글

boj 3109 빵집  (0) 2021.02.18
boj 17406 배열 돌리기 4  (0) 2021.02.10
boj 16926 배열 돌리기 1  (0) 2021.02.10
boj 1068 트리  (0) 2021.02.09
boj 9202 Boggle  (0) 2021.02.02

www.acmicpc.net/problem/16926

 

16926번: 배열 돌리기 1

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5] ↓ ↑ A[2][1] A[2][2] ← A[2][3] ← A[2][4] A[2][5]

www.acmicpc.net

입력으로 들어오는 배열을 이런식으로 회전시킨 결과를 출력하는 문제입니다..

무작정 짜보려고 했다가 소스만 두번정도 갈아엎고 찾은 솔루션이 dfs 방법입니다.

 

바깥쪽 그룹부터 안쪽 그룹 순서대로 회전하기때문에 시작지점은 항상 (i, i)입니다.

우선 가장 바깥쪽 그룹부터 구간을 (0, 0) ~ (N - 1, M - 1)으로 잡고 R번 회전 시킨 후에

구간을 (+1, +1), ~ (-1, -1)씩 하고 다음 그룹도 똑같이 회전시켜줍니다. (구간 범위가 벗어나면 break)

 

dfs에서는 방문처리를 count식으로 방문 횟수를 갱신하였습니다.

next가 범위를 벗어나면 방향을 바꾸고 next를 다시 구해줍니다.

만약 next의 방문횟수와 자신의 방문횟수가 같으면 한바퀴를 돌았다는 뜻이 됩니다.

=> list[x][y]에 list[nx][ny]를 넣고 원래 자신의 값을 리턴합니다.

그러면 이제 리턴되는 값들을 모두 받게되면 회전 1번을 하게 된것입니다.

 

그리고 회전시킬 때 회전시키는 배열의 크기 (n - 1) * 2 + (m - 1) * 2번이 한바퀴이므로 mod 연산을 통해 R을 낮춰준 후에 회전시켜줍니다. 다음 구간으로 넘어가면 크기를 2만큼 줄여줘야합니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int visit[][];
    static int list[][];
    static int N, M, R;
    static int sx, sy, ex, ey;
 
    static void print() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                sb.append(list[i][j] + " ");
            }
            sb.append("\n");
        }
 
        System.out.println(sb.toString());
    }
 
    static int dfs(int x, int y, int idx) {
        visit[x][y]++;
 
        int nx = x + direct[idx][0];
        int ny = y + direct[idx][1];
 
        if (nx < sx || ny < sy || nx > ex || ny > ey) {
            idx++;
            nx = x + direct[idx][0];
            ny = y + direct[idx][1];
        }
 
        if (visit[nx][ny] == visit[x][y]) {
            int tmp = list[x][y];
            list[x][y] = list[nx][ny];
            return tmp;
        }
 
        int tmp = list[x][y];
        list[x][y] = dfs(nx, ny, idx);
        return tmp;
    }
 
    static void solve() {
        sx = 0;
        sy = 0;
        ex = N - 1;
        ey = M - 1;
        int n = N;
        int m = M;
        for (int i = 0;; i++) {
            for (int j = 0; j < R % ((n - 1* 2 + (m - 1* 2); j++) {
                dfs(i, i, 0);
            }
            sx++;
            sy++;
            ex--;
            ey--;
            n -= 2;
            m -= 2;
            if (sx > ex || sy > ey)
                break;
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        R = Integer.parseInt(st.nextToken());
        list = new int[N][M];
        visit = new int[N][M];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        solve();
        print();
    }
}
cs

'algorithm > dfs' 카테고리의 다른 글

boj 17406 배열 돌리기 4  (0) 2021.02.10
boj 16927 배열 돌리기 2  (0) 2021.02.10
boj 1068 트리  (0) 2021.02.09
boj 9202 Boggle  (0) 2021.02.02
boj 15666 N과 M (12)  (0) 2021.01.31

www.acmicpc.net/problem/1068

 

1068번: 트리

첫째 줄에 트리의 노드의 개수 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에는 0번 노드부터 N-1번 노드까지, 각 노드의 부모가 주어진다. 만약 부모가 없다면 (루트) -1이 주어진다

www.acmicpc.net

각 노드의 부모노드가 입력으로 주어집니다. (루트노드인 경우에는 -1이 주어집니다.)

그리고 삭제할 노드가 주어집니다.

노드를 삭제하면 해당 노드의 자식노드들까지 모두 삭제됩니다.

노드를 삭제한 후의 리프노드 갯수를 구하는 문제입니다.

 

입력이 들어오면 ArrayList로 그래프를 만들어줍니다.

그리고 입력으로 -1이 주어지면 루트노드이므로 저장해둡니다.

 

이제 root를 시작으로 dfs를 돌려줍니다.

만약 v가 삭제할 노드면 바로 리턴시켜주고,

v의 자식이 없으면 (list[v].size() == 0) 리프노드입니다. => ans++

v의 자식이 1개이고 그게 삭제할 노드면 v는 리프노드가 됩니다. => ans++

위의 예외처리만 해주고 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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static ArrayList<Integer> list[];
    static int N, deleteNode, root, ans;
 
    static void dfs(int v) {
        if (v == deleteNode)
            return;
 
        if (list[v].size() == 0) {
            ans++;
            return;
        }
 
        for (int i = 0; i < list[v].size(); i++) {
            int next = list[v].get(i);
            
            if(list[v].size()==1 && next == deleteNode) {
                ans++;
                return;
            }
            
            dfs(next);
        }
    }
 
    static void input() throws Exception {
        int x;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new ArrayList[N];
        for (int i = 0; i < N; i++)
            list[i] = new ArrayList<>();
 
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) {
            x = Integer.parseInt(st.nextToken());
            if (x != -1)
                list[x].add(i);
            else
                root = i;
        }
 
        st = new StringTokenizer(br.readLine());
        deleteNode = Integer.parseInt(st.nextToken());
    }
 
    public static void main(String[] args) throws Exception {
        input();
        dfs(root);
        System.out.println(ans);
    }
}
cs

'algorithm > dfs' 카테고리의 다른 글

boj 16927 배열 돌리기 2  (0) 2021.02.10
boj 16926 배열 돌리기 1  (0) 2021.02.10
boj 9202 Boggle  (0) 2021.02.02
boj 15666 N과 M (12)  (0) 2021.01.31
boj 15665 N과 M (11)  (0) 2021.01.30

www.acmicpc.net/problem/13116

 

13116번: 30번

첫 번째 줄에 테스트 케이스의 수 T (1 ≤ T ≤ 50 000)가 주어진다. 이후 T개의 테스트 케이스가 주어진다. 각 테스트 케이스는 한 줄로 구성되어 있으며, 각 줄에는 두 개의 정수 A와 B (1 ≤ A, B ≤ 1

www.acmicpc.net

사실 링크없이 이문제만 올려놔도 될 정도입니다..

위의 사진처럼 1 ~ 1023까지 perfect binary tree를 구성하고 있습니다.

여기서 a와 b의 최소 공통조상노드를 구하는 문제입니다.

 

트리는 고정이기때문에 depth와 parent는 입력을 받기전에 미리 구성해줍니다.

우선 dfs로 탐색을 진행하여 노드의 깊이를 저장해줍니다.

dfs로 탐색을 진행하면서 parent[v][0]에 부모노드인 v / 2를 저장합니다.

그 다음 parent배열에 자신의 1, 2, 4, 8, ... (2^N)번째 조상노드를 저장합니다.

 

입력으로 x, y를 받으면 x와 y의 최소 공통조상노드를 구합니다.

우선 y의 깊이가 더 크게 맞춰놓고

y의 깊이를 x에 맞춰줍니다.

 

그 다음 x와 y의 조상이 같아질때까지

x = parent[x][i]

y = parent[y][i]

연산을 반복합니다.

 

최종적으로 parent[x][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
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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static int depth[] = new int[1024];
    static int parent[][] = new int[1024][11];
 
    static void dfs(int v, int d) {
        depth[v] = d;
        parent[v][0= v / 2;
 
        int next = v * 2;
 
        if (next >= 1024)
            return;
 
        dfs(next, d + 1);
        dfs(next + 1, d + 1);
    }
 
    static void init() {
        dfs(11);
        for (int j = 1; j < 11; j++) {
            for (int i = 1; i <= 1023; i++) {
                parent[i][j] = parent[parent[i][j - 1]][j - 1];
            }
        }
    }
 
    static int lca(int x, int y) {
        if (depth[x] > depth[y]) {
            int tmp = x;
            x = y;
            y = tmp;
        }
 
        for (int i = 10; i >= 0; i--) {
            if (depth[y] - depth[x] >= (1 << i)) {
                y = parent[y][i];
            }
        }
 
        if (x == y)
            return x;
 
        for (int i = 10; i >= 0; i--) {
            if (parent[x][i] != parent[y][i]) {
                x = parent[x][i];
                y = parent[y][i];
            }
        }
        
        return parent[x][0];
    }
 
    static void input() throws Exception {
        int u, v;
        st = new StringTokenizer(br.readLine());
        u = Integer.parseInt(st.nextToken());
        v = Integer.parseInt(st.nextToken());
 
        sb.append(lca(u, v) * 10 + "\n");
    }
 
    public static void main(String[] args) throws Exception {
        init();
        st = new StringTokenizer(br.readLine());
        int tc = Integer.parseInt(st.nextToken());
        while (tc-- > 0) {
            input();
        }
        
        System.out.println(sb.toString());
    }
}
cs

'algorithm > LCA' 카테고리의 다른 글

boj 1626 두 번째로 작은 스패닝 트리  (0) 2021.04.02
boj 15481 그래프와 MST  (0) 2021.04.01
boj 15480 LCA와 쿼리  (0) 2021.02.14
boj 11438 LCA 2  (0) 2021.02.11
boj 11437 LCA  (0) 2021.02.11

www.acmicpc.net/problem/9372

 

9372번: 상근이의 여행

첫 번째 줄에는 테스트 케이스의 수 T(T ≤ 100)가 주어지고, 각 테스트 케이스마다 다음과 같은 정보가 주어진다. 첫 번째 줄에는 국가의 수 N(2 ≤ N ≤ 1 000)과 비행기의 종류 M(1 ≤ M ≤ 10 000) 가

www.acmicpc.net

이문제는 모든 국가를 여행하는데 타야하는 비행기의 최소 갯수를 출력하는 문제입니다.

입력으로는 무조건 연결그래프만 주어지며, N개의 국가를 모두 연결하기 위해서는 최소 N - 1개의 간선만 있으면 됩니다.

입력만 다받고 N - 1를 출력해줍시다.

 

 

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
package BOJ.data_structure;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Boj9372 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static int N;
 
    static void input() throws Exception {
        int M, x;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        while (M-- > 0) {
            st = new StringTokenizer(br.readLine());
            x = Integer.parseInt(st.nextToken());
            x = Integer.parseInt(st.nextToken());
        }
 
        sb.append(N - 1 + "\n");
    }
 
    public static void main(String[] args) throws Exception {
        st = new StringTokenizer(br.readLine());
        int tc = Integer.parseInt(st.nextToken());
        while (tc-- > 0) {
            input();
        }
        
        System.out.println(sb.toString());
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 21939 문제 추천 시스템 Version 1  (0) 2022.02.11
boj 17299 오등큰수  (0) 2021.02.22
boj 1158 요세푸스 문제  (0) 2021.02.09
boj 1918 후위 표기식  (0) 2021.02.05
boj 1935 후위 표기식2  (0) 2021.02.05

www.acmicpc.net/problem/1158

 

1158번: 요세푸스 문제

첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 5,000)

www.acmicpc.net

1 ~ N 까지 순서대로 저장되어있으면 매번 K번째 수를 제거하고, 제거되는 숫자 순서대로 출력하는 문제입니다.

 

저는 덱을 이용하여 1 ~ N 까지의 숫자를 넣었고, K번째 수를 제거하기 위해 1 ~ K - 1번째 수를 뒤로 보낸 후에 제거하였습니다.

 

원래 큐를 이용하는 문제지만 저는 덱이 먼저 떠올라서 덱으로 풀었습니다.

하지만 이유는 모르겠으나 메모리와 시간 차이가 있었습니다.

Queue를 이용한 풀이

 

Deque를 이용한 풀이

무슨 이유일까요... 소스 두개모두 올립니다...

아마 ArrayDeque와 LinkedList의 차이인것 같습니다..

LinkedList가 좌 우를 연결하는 link를 다루기때문에 이에대한 추가 메모리 발생과 link 연결을 위한 연산시간이 추가로 발생하는게 아닌가하는 생각이 듭니다.

 

 

[Queue]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static Queue<Integer> q = new LinkedList<>();
    static int N, K;
 
    static void func() {
        sb.append("<");
        while (!q.isEmpty()) {
            for (int i = 0; i < K - 1; i++) {
                q.add(q.poll());
            }
 
            sb.append(q.poll());
            if (!q.isEmpty())
                sb.append(", ");
        }
        sb.append(">");
 
        System.out.println(sb.toString());
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
 
        for (int i = 1; i <= N; i++)
            q.add(i);
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

 

 

[Deque]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static Deque<Integer> dq = new ArrayDeque<>();
    static int N, K;
 
    static void func() {
        sb.append("<");
        while (!dq.isEmpty()) {
            for (int i = 0; i < K - 1; i++) {
                dq.addLast(dq.pollFirst());
            }
 
            sb.append(dq.pollFirst());
            if (!dq.isEmpty())
                sb.append(", ");
        }
        sb.append(">");
 
        System.out.println(sb.toString());
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
 
        for (int i = 1; i <= N; i++)
            dq.addLast(i);
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > data-structure' 카테고리의 다른 글

boj 17299 오등큰수  (0) 2021.02.22
boj 9372 상근이의 여행  (0) 2021.02.09
boj 1918 후위 표기식  (0) 2021.02.05
boj 1935 후위 표기식2  (0) 2021.02.05
boj 2493 탑  (0) 2021.02.04

www.acmicpc.net/problem/10826

 

10826번: 피보나치 수 4

피보나치 수는 0과 1로 시작한다. 0번째 피보나치 수는 0이고, 1번째 피보나치 수는 1이다. 그 다음 2번째 부터는 바로 앞 두 피보나치 수의 합이 된다. 이를 식으로 써보면 Fn = Fn-1 + Fn-2 (n ≥ 2)가

www.acmicpc.net

 

점화식 : dp[i] = dp[i - 1] + dp[i - 2]

앞의 두 개의 수를 더한 값이 자신의 값이 됩니다.

 

이 문제는 N이 10000까지 오기때문에 long의 범위를 초과합니다.

자바에는 BigInteger라는 클래스가 있기때문에 이용 사용하여 쉽게 구할 수 있습니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int N;
 
    static void solve() {
        BigInteger dp[] = new BigInteger[10001];
        dp[0= new BigInteger("0");
        dp[1= new BigInteger("1");
        for (int i = 2; i <= N; i++) {
            dp[i] = dp[i - 1].add(dp[i - 2]);
        }
 
        System.out.println(dp[N]);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
    }
 
    public static void main(String[] args) throws Exception {
        input();
        solve();
    }
}
cs

'algorithm > dp' 카테고리의 다른 글

boj 1912 연속합  (0) 2021.02.18
boj 10211 Maximum Subarray  (0) 2021.02.18
boj 5569 출근 경로  (0) 2021.02.06
boj 1010 다리 놓기  (0) 2021.02.05
boj 5557 1학년  (0) 2021.02.05

www.acmicpc.net/problem/20304

 

20304번: 비밀번호 제작

서강대학교 전산실에서 보안직원으로 일하는 향빈이는 한 통의 이메일을 받게 되었다. 이메일에는 서버 관리자 계정에 대한 비정상적인 로그인 시도가 감지되었다는 내용이 적혀 있었고, 첨부

www.acmicpc.net

bfs에 비트마스킹까지 해야하는 문제입니다.

 

관리자 계정 비밀번호와 해커가 로그인 시도에 사용된 비밀번호의 안전거리로 계산한 안전도를 최대로 해야합니다.

우선 로그인 시도에 사용된 비밀번호가 관리자 계정 비밀번호와 같으면 안전거리는 0입니다. (고정)

이를 큐에 넣고 비트마스킹을 이용하여 bfs로 탐색을 합니다. 큐에는 번호와 안전도를 유지합니다.

 

이제 1부터 왼쪽시프트를 하면서 x와 &연산을 합니다. (y = x & i)

y > 0이면 같은 자릿수가 있다는 의미이며, x - i를 한 값이 거리가 1인 숫자입니다.

그리고 y == 0이면 같은 자릿수가 없다는 의미이며, x + i를 한 값이 거리가 1인 숫자입니다.

 

이 과정을 반복하여 cnt의 max를 구하여 출력합니다.

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Queue<int[]> q = new LinkedList<>();
    static int visit[];
    static int N, M, ans;
 
    static void bfs() {
        while (!q.isEmpty()) {
            int x = q.peek()[0];
            int cnt = q.poll()[1];
 
            ans = Math.max(ans, cnt);
            for (int i = 1; i <= N; i = i << 1) {
                int y = x & i;
 
                if (y > 0) {
                    if (visit[x - i] != -1)
                        continue;
                    q.add(new int[] { x - i, cnt + 1 });
                    visit[x - i] = cnt + 1;
                } else {
                    if (x + i > N || visit[x + i] != -1)
                        continue;
                    q.add(new int[] { x + i, cnt + 1 });
                    visit[x + i] = cnt + 1;
                }
            }
        }
 
        System.out.println(ans);
    }
 
    static void input() throws Exception {
        int x;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        visit = new int[N + 1];
        Arrays.fill(visit, -1);
 
        st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
 
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < M; i++) {
            x = Integer.parseInt(st.nextToken());
            q.add(new int[] { x, 0 });
            visit[x] = 0;
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 2206 벽 부수고 이동하기  (0) 2021.02.13
boj 14502 연구소  (0) 2021.02.12
boj 2606 바이러스  (0) 2021.02.03
boj 1012 유기농 배추  (0) 2021.02.03
boj 16956 늑대와 양  (0) 2021.02.03

www.acmicpc.net/problem/1914

 

1914번: 하노이 탑

세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로

www.acmicpc.net

emoney96.tistory.com/102

 

boj 11729 하노이 탑 이동 순서

www.acmicpc.net/problem/11729 11729번: 하노이 탑 이동 순서 세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이

emoney96.tistory.com

이 문제랑 같은 문제입니다.

이동 순서는 위의 문제와 동일하게 해주시면 됩니다.

 

하나 다른점은 N이 최대 100이며, N>20인 경우에는 횟수만 출력합니다.

2^100 - 1 = 1267650600228229401496703205375 이므로 long의 범위도 초과합니다.

그래서 자바의 BigInteger를 사용합니다.

BigInteger에 pow라는 지수메소드가 있어서 2^N을 구할 수 있고, subtract 메소드로 1을 감소시켜줍니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static BigInteger ans = new BigInteger("2");
    static int N;
 
    static void func(int n, int a, int b, int c) {
        if (n < 1)
            return;
 
        func(n - 1, a, c, b);
        sb.append(a + " " + c + "\n");
        func(n - 1, b, a, c);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
 
        ans = ans.pow(N).subtract(new BigInteger("1"));
    }
 
    public static void main(String[] args) throws Exception {
        input();
        System.out.println(ans);
        if (N > 20) {
            return;
        }
        func(N, 123);
        System.out.println(sb.toString());
    }
}
cs

'algorithm > Implementation' 카테고리의 다른 글

boj 16918 봄버맨  (0) 2021.02.17
boj 16935 배열 돌리기 3  (0) 2021.02.10
boj 11729 하노이 탑 이동 순서  (0) 2021.02.07
boj 1244 스위치 켜고 끄기  (0) 2021.02.01
boj 20127 Y-수열  (0) 2021.01.22

www.acmicpc.net/problem/11729

 

11729번: 하노이 탑 이동 순서

세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로

www.acmicpc.net

하노이탑 이동 횟수와 순서를 출력하는 문제입니다.

 

하노이탑은 3개의 기둥이 있고, 한 기둥에 원판들이 작은 것이 위에 있고 순서대로 밑으로 쌓여있습니다.

한 번에 하나의 원판만 옮길 수 있고, 큰 원판이 작은 원판 위에 있으면 안됩니다.

 

일단 원판이 n개 일 때, 이동 횟수는 2^n - 1개입니다.

비트연산을 이용하면 빠르게 구할 수 있습니다.

 

그리고, 재귀를 통해 순서를 출력해주시면 됩니다.

저는 "func(n, a, b, c) : n개의 원판이 a에서 c로 이동하는 경우" 이렇게 함수를 선언하였습니다.

그 다음 n - 1개를 a에서 b로 옮기고, 나머지 1개를 a에서 c로 옮기고, n - 1개를 b에서 c를 옮기는 로직입니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static int N;
 
    static void func(int n, int a, int b, int c) {
        if (n < 1)
            return;
        func(n - 1, a, c, b);
        sb.append(a + " " + c + "\n");
        func(n - 1, b, a, c);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
 
        sb.append((2 << (N - 1)) - 1 + "\n");
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func(N, 123);
        System.out.println(sb.toString());
    }
}
cs

'algorithm > Implementation' 카테고리의 다른 글

boj 16918 봄버맨  (0) 2021.02.17
boj 16935 배열 돌리기 3  (0) 2021.02.10
boj 1914 하노이 탑  (0) 2021.02.07
boj 1244 스위치 켜고 끄기  (0) 2021.02.01
boj 20127 Y-수열  (0) 2021.01.22

+ Recent posts