www.acmicpc.net/problem/19236

 

19236번: 청소년 상어

첫째 줄부터 4개의 줄에 각 칸의 들어있는 물고기의 정보가 1번 행부터 순서대로 주어진다. 물고기의 정보는 두 정수 ai, bi로 이루어져 있고, ai는 물고기의 번호, bi는 방향을 의미한다. 방향 bi는

www.acmicpc.net

이 문제는 고려해야할 부분이 많습니다.

 

상어와 물고기는 8방향 이동을 할 수 있습니다.

순서는 (1)상어가 물고기를 먹고 (2)물고기들이 이동합니다.

상어가 처음에는 (0, 0)에 있는 물고기를 먹으며 먹은 물고기의 방향을 갖게되고, 이후에는 주어진 방향으로만 이동합니다.

 

상어는 한 번에 여러 칸을 이동할 수 있고, 물고기가 있는 칸으로만 이동할 수 있습니다.

따라서 이동경로에 있는 물고기 후보 중 하나를 골라 먹습니다.

 

물고기는 맵 밖이나 상어가 있는 칸으로 이동할 수 없으며 이동할 때 번호가 작은 물고기부터 순서대로 이동합니다. (1번 ~ 16번)

(만약, 해당 번호의 물고기가 먹힌상태면 다음 번호가 이동하면 됩니다.)

물고기는 주어진 방향으로만 1칸 이동하며, 그 칸에 물고기가 있으면 서로의 자리를 바꿉니다.

만약 물고기가 이동할 수 없는 경우에는 이동할 수 있을 때까지 방향을 45도 반시계 방향으로 회전한 후 이동합니다.

 

 

이제 제 로직을 설명하겠습니다.

 

저는 입력을 받으면서 (0, 0)에 상어를 미리 놓고, (1)물고기들 이동, (2)상어 이동 순서대로 구현하였습니다.

func함수의 파라미터에 (현재 배열의 상태(arr), 물고기의 상태(f), 상어의 좌표(X, Y), 상어의 방향(D), 현재 먹은 물고기들의 번호합(S))

을 넘겨주는 재귀함수로 구성하였습니다.

 

함수가 돌 때마다 최대 합을 갱신해주었고, 물고기 이동부터 시작합니다.

먹히지 않은 물고기들만 이동하는 방식이며, 물고기가 이동할 수 있을 때까지 방향을 45도씩 반시계방향으로 회전시키며 반복문을 돌렸습니다.

물고기가 이동하고나면 break를 합니다.

 

이제 상어가 이동합니다.

상어는 한 방향으로만 움직일 수 있지만 여러 칸 이동이 가능하므로 맵 밖으로 나갈 때까지 반복문을 돌려줍니다.

물고기가 없는 칸은 갈 수 없으므로 continue를 하였고, 물고기가 있는 칸은 먹은 후의 상태를 다음 재귀로 넘겨주었습니다. (이는 백트래킹으로 구현하였습니다.)

 

상어와 물고기의 모든 이동이 끝나면 계속 갱신해주었던 답을 출력해줍니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static class Pair {
        int x, y, d;
 
        public Pair(int x, int y, int d) {
            this.x = x;
            this.y = y;
            this.d = d;
        }
    }
 
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int direct[][] = { { -10 }, { -1-1 }, { 0-1 }, { 1-1 }, { 10 }, { 11 }, { 01 }, { -11 } };
    static boolean eat[] = new boolean[17];
    static int ans;
 
    static void func(int[][] arr, Pair[] f, int X, int Y, int D, int S) {
        ans = Math.max(ans, S);
        for (int i = 1; i <= 16; i++) {
            if (eat[i])
                continue;
 
            int x = f[i].x;
            int y = f[i].y;
 
            int nx = x;
            int ny = y;
 
            while (true) {
                nx = x + direct[f[i].d][0];
                ny = y + direct[f[i].d][1];
 
                if (nx < 0 || ny < 0 || nx >= 4 || ny >= 4) {
                    f[i].d = (f[i].d + 1) % 8;
                    continue;
                }
                if (arr[nx][ny] == -1) {
                    f[i].d = (f[i].d + 1) % 8;
                    continue;
                }
 
                if (arr[nx][ny] == 0) {
                    f[i].x = nx;
                    f[i].y = ny;
                    arr[nx][ny] = arr[x][y];
                    arr[x][y] = 0;
                } else {
                    int tmp = arr[x][y];
                    f[arr[nx][ny]].x = x;
                    f[arr[nx][ny]].y = y;
                    f[i].x = nx;
                    f[i].y = ny;
                    arr[x][y] = arr[nx][ny];
                    arr[nx][ny] = tmp;
                }
                break;
            }
        }
 
        int nx = X;
        int ny = Y;
        while (true) {
            nx = nx + direct[D][0];
            ny = ny + direct[D][1];
 
            if (nx < 0 || ny < 0 || nx >= 4 || ny >= 4)
                break;
            if (arr[nx][ny] == 0)
                continue;
 
            int tmp = arr[nx][ny];
            arr[nx][ny] = -1;
            arr[X][Y] = 0;
            eat[tmp] = true;
            int arr2[][] = new int[4][4];
            for (int i = 0; i < 4; i++)
                arr2[i] = arr[i].clone();
            Pair f2[] = new Pair[17];
            for (int i = 1; i <= 16; i++)
                f2[i] = new Pair(f[i].x, f[i].y, f[i].d);
            func(arr2, f2, nx, ny, f[tmp].d, S + tmp);
            eat[tmp] = false;
            arr[nx][ny] = tmp;
            arr[X][Y] = -1;
        }
    }
 
    public static void main(String[] args) throws Exception {
        int list[][] = new int[4][4];
        Pair fish[] = new Pair[17];
 
        int nowx = 0, nowy = 0, nowd = 0, sum = 0;
        int x, d;
        for (int i = 0; i < 4; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < 4; j++) {
 
                x = Integer.parseInt(st.nextToken());
                d = Integer.parseInt(st.nextToken()) - 1;
 
                list[i][j] = x;
                fish[x] = new Pair(i, j, d);
                if (i == 0 && j == 0) {
                    list[i][j] = -1;
                    eat[x] = true;
                    nowx = i;
                    nowy = j;
                    nowd = d;
                    sum += x;
                }
            }
        }
        func(list, fish, nowx, nowy, nowd, sum);
        System.out.println(ans);
    }
}
cs

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

boj 2239 스도쿠  (0) 2021.04.16
boj 2458 키 순서  (0) 2021.04.13
boj 14889 스타트와 링크  (0) 2021.03.17
boj 2023 신기한 소수  (0) 2021.03.16
boj 14500 테트로미노  (0) 2021.03.15

www.acmicpc.net/problem/2239

 

2239번: 스도쿠

스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다

www.acmicpc.net

백트래킹 기본문제 중 하나입니다.

우선 스도쿠는 9 * 9 배열이 있을 때 각 행, 열, 3 * 3구간에서 1 ~ 9가 한 번씩만 나오게 하는 문제입니다.

 

그럼 각 행, 열, 구간을 중복체크하는 배열을 세개 사용합니다.

(0, 0)부터 (8, 8)까지 한 칸씩 확인하며, list[x][y] != 0이면 수를 넣을 필요가 없으므로 바로 다음좌표를 탐색합니다.

list[x][y] == 0이면 1 ~ 9까지 넣을 수 있는지 확인합니다.

(x, y)에서 숫자 i가 x행에서 사용되었는지, y열에서 사용되었는지, 같은 구간에서 사용되었는지 각각 확인해줍니다.

세 구간 모두 사용되지 않은 숫자만 list[x][y]에 넣어주고 다음좌표로 넘겨줍니다.

모든 좌표를 탐색하였으면 답을 출력하고 리턴합니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
    static char div[][] = { { 'a''a''a''b''b''b''c''c''c' },
            { 'a''a''a''b''b''b''c''c''c' }, { 'a''a''a''b''b''b''c''c''c' },
            { 'd''d''d''e''e''e''f''f''f' }, { 'd''d''d''e''e''e''f''f''f' },
            { 'd''d''d''e''e''e''f''f''f' }, { 'g''g''g''h''h''h''i''i''i' },
            { 'g''g''g''h''h''h''i''i''i' }, { 'g''g''g''h''h''h''i''i''i' }, };
    static boolean rowsChk[][] = new boolean[10][10];
    static boolean colsChk[][] = new boolean[10][10];
    static boolean divChk[][] = new boolean[10][10];
    static int list[][] = new int[10][10];
 
    static boolean func(int x, int y) {
        if (x == 9) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    sb.append(list[i][j]);
                }
                sb.append("\n");
            }
            System.out.println(sb.toString());
            return true;
        }
 
        int nx = x;
        int ny = y + 1;
        if (ny == 9) {
            nx++;
            ny = 0;
        }
 
        if (list[x][y] != 0)
            return func(nx, ny);
        else {
            for (int i = 1; i <= 9; i++) {
                if (rowsChk[x][i] || colsChk[y][i] || divChk[div[x][y] - 'a'][i])
                    continue;
 
                rowsChk[x][i] = true;
                colsChk[y][i] = true;
                divChk[div[x][y] - 'a'][i] = true;
                list[x][y] = i;
                boolean chk = func(nx, ny);
                if (chk)
                    return true;
                list[x][y] = 0;
                divChk[div[x][y] - 'a'][i] = false;
                colsChk[y][i] = false;
                rowsChk[x][i] = false;
            }
        }
 
        return false;
    }
 
    static void input() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        char ch[];
        for (int i = 0; i < 9; i++) {
            st = new StringTokenizer(br.readLine());
            ch = st.nextToken().toCharArray();
            for (int j = 0; j < 9; j++) {
                list[i][j] = ch[j] - '0';
                if (list[i][j] != 0) {
                    rowsChk[i][list[i][j]] = true;
                    colsChk[j][list[i][j]] = true;
                    divChk[div[i][j] - 'a'][list[i][j]] = true;
                }
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func(00);
    }
}
cs

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

boj 19236 청소년 상어  (0) 2021.04.22
boj 2458 키 순서  (0) 2021.04.13
boj 14889 스타트와 링크  (0) 2021.03.17
boj 2023 신기한 소수  (0) 2021.03.16
boj 14500 테트로미노  (0) 2021.03.15

www.acmicpc.net/problem/2458

 

2458번: 키 순서

1번부터 N번까지 번호가 붙여져 있는 학생들에 대하여 두 학생끼리 키를 비교한 결과의 일부가 주어져 있다. 단, N명의 학생들의 키는 모두 다르다고 가정한다. 예를 들어, 6명의 학생들에 대하여

www.acmicpc.net

 

처음에 이 그림을 보았을 때 위상정렬을 쓰는건가 하고 생각했었지만 순서 중 하나를 출력하는 것이 아닌 자신의 정확한 순서를 알고있는 학생의 수를 출력하는 문제였습니다.

 

저는 두 가지 방법으로 해결하였습니다.

먼저 dfs 방법입니다.

 

저는 2개의 벡터를 사용하였습니다. (자신보다 키가 큰 학생을 저장하는 벡터(f), 작은 학생을 저장하는 벡터(s))

한 학생을 시작으로 두번의 dfs를 수행합니다.

i번 학생보다 키가 큰 학생들을 dfs로 순회하고, 작은 학생들도 똑같이 dfs로 순회합니다.

순회하면서 next의 갯수만큼 cnt를 1씩 늘려줍니다.

 

두 번의 dfs가 끝나고 cnt가 N - 1이면 자신의 정확한 순서를 알 수 있습니다.

 

 

그 다음은 플로이드 방법입니다.

 

d[i][j] : i번 학생의 키 < j번 학생의 키 인 경우

 

플로이드로 자신보다 키가 큰 학생들을 모두 구합니다.

그 다음 i번 학생과 j번 학생의 관계를 확인합니다.

d[i][j] (i번이 j번보다 작은 경우) || d[j][i] (i번이 j번보다 큰 경우)

 

위의 조건을 만족한 횟수가 N - 1이면 자신의 정확한 순서를 알 수 있습니다.

 

dfs
플로이드

 

아무래도 플로이드가  N^3이라 dfs에 비해 속도가 느린 편입니다.

 

 

[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
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
 
vector<int> f[501], s[501];
bool visit[501];
int N, M, cnt;
 
void dfs(vector<int> t[], int v) {
    visit[v] = true;
 
    for (int i = 0; i < t[v].size(); i++) {
        int next = t[v][i];
 
        if (visit[next]) continue;
 
        cnt++;
        dfs(t, next);
    }
}
 
void func() {
    int ans = 0;
    for (int i = 1; i <= N; i++) {
        memset(visit, falsesizeof(visit));
        dfs(f, i);
        memset(visit, falsesizeof(visit));
        dfs(s, i);
 
        if (cnt == N - 1) ans++;
        cnt = 0;
    }
 
    cout << ans << '\n';
}
 
void input() {
    int u, v;
    cin >> N >> M;
    while (M--) {
        cin >> u >> v;
        f[u].push_back(v);
        s[v].push_back(u);
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

 

 

[플로이드]

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>
#define INF 1000000000
using namespace std;
 
bool d[501][501];
int N, M, ans;
 
void solve() {
    for (int i = 1; i <= N; i++) {
        int cnt = 0;
        for (int j = 1; j <= N; j++) {
            if (d[i][j] || d[j][i]) cnt++;
        }
 
        if (cnt == N - 1) ans++;
    }
 
    cout << ans << '\n';
}
 
void func() {
    for (int k = 1; k <= N; k++) {
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                if (d[i][k] && d[k][j]) {
                    d[i][j] = true;
                }
            }
        }
    }
}
 
void input() {
    int u, v;
    cin >> N >> M;
    while (M--) {
        cin >> u >> v;
        d[u][v] = true;
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
    solve();
 
 
    return 0;
}
cs

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

boj 19236 청소년 상어  (0) 2021.04.22
boj 2239 스도쿠  (0) 2021.04.16
boj 14889 스타트와 링크  (0) 2021.03.17
boj 2023 신기한 소수  (0) 2021.03.16
boj 14500 테트로미노  (0) 2021.03.15

www.acmicpc.net/problem/14889

 

14889번: 스타트와 링크

예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.

www.acmicpc.net

조합으로 N/2개를 뽑은 후에 뽑은 것들의 조합의 능력치를 N^2으로 각각 계산해줍니다.

그 다음 abs(a-b)의 차이의 최소를 구해 출력해주시면 됩니다.

 

 

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
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 boolean pick[] = new boolean[21];
    static int list[][] = new int[21][21];
    static int N, ans = Integer.MAX_VALUE;
 
    static void func(int idx, int cnt) {
        if (cnt == N / 2) {
            int a = 0;
            int b = 0;
            for (int i = 0; i < N; i++) {
                for (int j = i + 1; j < N; j++) {
                    if (pick[i] == pick[j]) {
                        if (pick[i])
                            a += (list[i][j] + list[j][i]);
                        else
                            b += (list[i][j] + list[j][i]);
                    }
                }
            }
 
            ans = Math.min(ans, Math.abs(a - b));
            return;
        }
 
        for (int i = idx; i < N; i++) {
            pick[i] = true;
            func(i + 1, cnt + 1);
            pick[i] = false;
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func(00);
        System.out.println(ans);
    }
}
cs

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

boj 2239 스도쿠  (0) 2021.04.16
boj 2458 키 순서  (0) 2021.04.13
boj 2023 신기한 소수  (0) 2021.03.16
boj 14500 테트로미노  (0) 2021.03.15
boj 16922 로마 숫자 만들기  (0) 2021.02.24

www.acmicpc.net/problem/2023

 

2023번: 신기한 소수

수빈이가 세상에서 가장 좋아하는 것은 소수이고, 취미는 소수를 가지고 노는 것이다. 요즘 수빈이가 가장 관심있어 하는 소수는 7331이다. 7331은 소수인데, 신기하게도 733도 소수이고, 73도 소수

www.acmicpc.net

메모리 제한이 4MB이라서 에라토스테네스의 체를 사용할 수 없습니다.

그래서 소수인지 판별하는 부분을 2부터 반복문을 돌리는 방법을 선택해서 시간초과가 뜰것 같았지만 다행히도 AC를 받았습니다.

 

우선 문제의 7331을 보면 7331도 소수, 733도 소수, 73도 소수, 7도 소수입니다.

즉 일의자리부터 숫자 하나씩 뺀 부분 숫자도 소수여야합니다.

 

저는 백트래킹으로 맨 앞의 자리부터 구하였습니다.

우선 맨 앞의 자리에 올 수 있는 숫자는 2, 3, 5, 7입니다. (일의자리 소수)

각 숫자가 맨 앞의 올 경우를 구하기 위해 4번의 dfs를 돌립니다.

 

dfs에서는 일의자리로 올 숫자를 구하는것이기 때문에 짝수가 올 수 없으므로 홀수만 돌려줍니다.

next가 소수이면 재귀를 돌려주었고, 뽑은 숫자가 N개가 되면 지금까지 뽑은 숫자를 출력합니다.

 

 

[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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
using namespace std;
 
int N;
 
bool prime(int x) {
    for (int i = 2; i*<= x; i++) {
        if (!(x % i)) return false;
    }
 
    return true;
}
 
void dfs(int cnt, int x) {
    if (cnt == N) {
        cout << x << '\n';
        return;
    }
 
    for (int i = 1; i <= 9; i += 2) {
        int next = x * 10 + i;
        if (!prime(next)) continue;
        dfs(cnt + 1, next);
    }
}
 
void func() {
    dfs(12);
    dfs(13);
    dfs(15);
    dfs(17);
}
 
void input() {
    cin >> N;
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

 

 

[Java]

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
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 boolean primeCheck(int x) {
        for (int i = 2; i * i <= x; i++) {
            if (x % i == 0)
                return false;
        }
 
        return true;
    }
 
    static void dfs(int cnt, int x) {
        if (cnt == N) {
            sb.append(x).append("\n");
            return;
        }
 
        for (int i = 1; i <= 9; i += 2) {
            int next = x * 10 + i;
            if (!primeCheck(next))
                continue;
 
            dfs(cnt + 1, next);
        }
    }
 
    static void func() {
        dfs(12);
        dfs(13);
        dfs(15);
        dfs(17);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
        System.out.print(sb.toString());
    }
}
cs

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

boj 2458 키 순서  (0) 2021.04.13
boj 14889 스타트와 링크  (0) 2021.03.17
boj 14500 테트로미노  (0) 2021.03.15
boj 16922 로마 숫자 만들기  (0) 2021.02.24
boj 1987 알파벳  (0) 2021.02.18

www.acmicpc.net/problem/14500

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

크기가 N * M인 종이에 위와 같은 테트로미노를 하나 놓습니다.

그리고 이 테트로미노는 회전, 대칭한 모양이 가능합니다.

 

한개를 놓으면 되기때문에 각 칸에서의 모든 경우를 다 체크해야합니다.

테트로미노 중 'ㅏ', 'ㅓ', 'ㅗ', 'ㅜ' 모양을 제외하면 한붓 그리기가 가능하므로 dfs로 구할 수 있습니다.

dfs로 가능한 모양들은 dfs를 돌려줘서 4칸을 방문할 때마다 ans를 갱신해줍니다.

 

 

 

그 다음 한붓그리기가 안되는 모양인 'ㅏ', 'ㅓ', 'ㅗ', 'ㅜ' 모양에 대한 처리를 합니다.

저는 이 모양들을 좌표로 이용하였습니다.

 

 

위와 같은 그림처럼 좌표값을 하나하나 비교하였고 각 모양마다 올 수 있는 최소, 최대 좌표값의 범위를 체크하고, 

각각 합의 최댓값을 갱신해주었습니다.

 

 

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 <algorithm>
using namespace std;
 
int list[501][501];
bool visit[501][501];
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
int N, M, ans;
 
void dfs(int x, int y, int cnt, int sum) {
    if (cnt == 4) {
        ans = max(ans, sum);
        return;
    }
 
    for (int i = 0; i < 4; i++) {
        int nx = x + direct[i][0];
        int ny = y + direct[i][1];
 
        if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
        if (visit[nx][ny]) continue;
 
        visit[nx][ny] = true;
        dfs(nx, ny, cnt + 1, sum + list[nx][ny]);
        visit[nx][ny] = false;
    }
}
 
void func() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            visit[i][j] = true;
            dfs(i, j, 1, list[i][j]);
            visit[i][j] = false;
 
            if (i + 2 < N && j + 1 < M) {
                ans = max(ans, list[i][j] + list[i + 1][j] + list[i + 2][j] + list[i + 1][j + 1]);
            }
            if (i + 1 < N && j - 1 >= 0 && j + 1 < M) {
                ans = max(ans, list[i][j] + list[i + 1][j - 1+ list[i + 1][j] + list[i + 1][j + 1]);
            }
            if (i + 1 < N && j + 2 < M) {
                ans = max(ans, list[i][j] + list[i][j + 1+ list[i][j + 2+ list[i + 1][j + 1]);
            }
            if (i - 1 >= 0 && i + 1 < N && j + 1 < M) {
                ans = max(ans, list[i][j] + list[i - 1][j + 1+ list[i][j + 1+ list[i + 1][j + 1]);
            }
        }
    }
 
    cout << ans << '\n';
}
 
void input() {
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

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

boj 14889 스타트와 링크  (0) 2021.03.17
boj 2023 신기한 소수  (0) 2021.03.16
boj 16922 로마 숫자 만들기  (0) 2021.02.24
boj 1987 알파벳  (0) 2021.02.18
boj 3109 빵집  (0) 2021.02.18

www.acmicpc.net/problem/16922

 

16922번: 로마 숫자 만들기

2, 6, 10, 11, 15, 20, 51, 55, 60, 100을 만들 수 있다.

www.acmicpc.net

1, 5, 10, 50을 배열에 넣어놓고 조합으로 해결하였습니다.

인덱스와 갯수와 합을 유지시키면서 재귀를 돌려줍니다.

N개를 뽑으면 숫자를 저장하였는데 이 때 중복된 값을 넣으면 안되므로 set에 넣어줍니다.

함수가 끝나고 최종 set의 크기를 출력하시면 됩니다.

 

 

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
#include <iostream>
#include <set>
using namespace std;
 
set<int> s;
int list[4];
int N;
 
void init() {
    list[0= 1;
    list[1= 5;
    list[2= 10;
    list[3= 50;
}
 
void func(int idx, int cnt, int sum) {
    if (cnt == N) {
        if (sum > 0) s.insert(sum);
        return;
    }
 
    for (int i = idx; i < 4; i++) {
        func(i, cnt + 1, sum + list[i]);
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    cin >> N;
    init();
    func(000);
    cout << s.size() << '\n';
 
    return 0;
}
cs

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

boj 2023 신기한 소수  (0) 2021.03.16
boj 14500 테트로미노  (0) 2021.03.15
boj 1987 알파벳  (0) 2021.02.18
boj 3109 빵집  (0) 2021.02.18
boj 17406 배열 돌리기 4  (0) 2021.02.10

www.acmicpc.net/problem/1987

 

1987번: 알파벳

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으

www.acmicpc.net

 

문제에서 요구하는 조건은

1. 말은 (0, 0)에서 출발합니다.

2. 말은 상하좌우 방향으로 움직일 수 있습니다.

3. 말이 지나가는 동안 밟은 칸의 알파벳은 모두 달라야합니다.

 

말이 (0, 0)에서 출발하여 지나갈 수 있는 최대의 칸 수를 출력해야합니다.

저는 백트래킹으로 해결하였고 해당 칸을 방문체크하는 visit배열과 칸에 있는 알파벳 중복체크를 위한 alphachk 배열을 사용하였습니다.

 

재귀를 돌릴때마다 답을 갱신해주고, 해당 칸과 알파벳에 방문처리합니다.

그 다음 4방향 탐색하여 맵 밖으로 나갔는지, 이미 방문하였거나 밟은 적이 있는 알파벳인지 체크를 해줍니다.

모두 통과하면 nx, ny, cnt+1를 재귀로 넘겨주고, 빠져나오면 true했던 boolean배열을 모두 false로 바꿔줍니다.

마지막으로 정답을 출력합니다.

 

 

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
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 boolean visit[][], alphachk[];
    static char list[][];
    static int N, M, ans;
 
    static void dfs(int x, int y, int cnt) {
        ans = Math.max(ans, cnt);
        visit[x][y] = true;
        alphachk[list[x][y] - 'A'= true;
 
        for (int i = 0; i < 4; i++) {
            int nx = x + direct[i][0];
            int ny = y + direct[i][1];
 
            if (nx < 0 || ny < 0 || nx >= N || ny >= M)
                continue;
            if (visit[nx][ny] || alphachk[list[nx][ny] - 'A'])
                continue;
 
            dfs(nx, ny, cnt + 1);
            alphachk[list[nx][ny] - 'A'= false;
            visit[nx][ny] = false;
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        list = new char[N][];
        visit = new boolean[N][M];
        alphachk = new boolean[26];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i] = st.nextToken().toCharArray();
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        dfs(001);
        System.out.println(ans);
    }
}
cs

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

boj 14500 테트로미노  (0) 2021.03.15
boj 16922 로마 숫자 만들기  (0) 2021.02.24
boj 3109 빵집  (0) 2021.02.18
boj 17406 배열 돌리기 4  (0) 2021.02.10
boj 16927 배열 돌리기 2  (0) 2021.02.10

www.acmicpc.net/problem/3109

 

3109번: 빵집

유명한 제빵사 김원웅은 빵집을 운영하고 있다. 원웅이의 빵집은 글로벌 재정 위기를 피해가지 못했고, 결국 심각한 재정 위기에 빠졌다. 원웅이는 지출을 줄이고자 여기저기 지출을 살펴보던

www.acmicpc.net

 

파이프는 오른쪽, 대각선 오른쪽 위, 대각선 오른쪽 아래 방향으로 연결할 수 있고,

0번 열에서 M - 1번 열까지 파이프를 이어야하며 최종적으로 파이프라인의 최대 갯수를 출력하는 문제입니다.

 

저는 여기서 앞의 열에서 최대한 앞쪽의 열에 파이프를 연결하면 될것이라는 생각을 하여 백트래킹에 그리디알고리즘을 사용하였습니다.

 

(0, 0) ~ (N - 1, 0)까지 각각 dfs로 끝 열에 도달할 수 있는지 확인해줍니다.

그리디를 사용했기때문에 오른쪽 위 -> 오른쪽 -> 오른쪽 아래 방향 순으로 탐색해줍니다.

끝 열에 도달하면 true를 리턴해주고, 도달하지 못하면 false를 리턴합니다.

true일 경우에만 ans++를 하여 최종 답을 출력합니다.

 

visit배열을 초기화하지 않은 이유는

파이프는 겹칠수 없어서 앞쪽에서 연결한 파이프와 겹칠 수 있기 때문입니다.

만약 최종적으로 연결한 파이프가 아니라고 해도 그 위치에서는 파이프를 연결할 수 없다는 뜻이 되므로 초기화를 하지 않아야합니다.

 

 

[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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
using namespace std;
 
bool visit[10010][510];
char list[10010][510];
int direct[3][2= { {-1,1},{0,1},{1,1} };
int N, M, ans;
 
bool dfs(int x, int y) {
    visit[x][y] = true;
    if (y == M - 1return true;
 
    for (int i = 0; i < 3; i++) {
        int nx = x + direct[i][0];
        int ny = y + direct[i][1];
 
        if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
        if (visit[nx][ny] || list[nx][ny] == 'x'continue;
 
        bool chk = dfs(nx, ny);
        if (chk)
            return true;
    }
 
    return false;
}
 
void func() {
    for (int i = 0; i < N; i++) {
        if (dfs(i, 0)) ans++;
    }
 
    cout << ans << '\n';
}
 
void input() {
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

 

 

[Java]

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
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[][] = { { -11 }, { 01 }, { 11 } };
    static boolean visit[][];
    static char list[][];
    static int N, M, ans;
 
    static boolean dfs(int x, int y) {
        visit[x][y] = true;
        if (y == M - 1)
            return true;
 
        for (int i = 0; i < 3; i++) {
            int nx = x + direct[i][0];
            int ny = y + direct[i][1];
 
            if (nx < 0 || ny < 0 || nx >= N || ny >= M)
                continue;
            if (visit[nx][ny] || list[nx][ny] == 'x')
                continue;
 
            boolean chk = dfs(nx, ny);
            if (chk)
                return true;
        }
 
        return false;
    }
 
    static void func() {
        for (int i = 0; i < N; i++) {
            if (dfs(i, 0))
                ans++;
        }
 
        System.out.println(ans);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        list = new char[N][];
        visit = new boolean[N][M];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i] = st.nextToken().toCharArray();
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

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

boj 16922 로마 숫자 만들기  (0) 2021.02.24
boj 1987 알파벳  (0) 2021.02.18
boj 17406 배열 돌리기 4  (0) 2021.02.10
boj 16927 배열 돌리기 2  (0) 2021.02.10
boj 16926 배열 돌리기 1  (0) 2021.02.10

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/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

+ Recent posts