반응형

문제 링크: https://www.acmicpc.net/problem/2636

 

2636번: 치즈

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓

www.acmicpc.net

<문제 풀이> BFS

X로 표시된 곳엔 치즈가 없으니깐 X로 표시된 곳 중 한 곳에서 공기가 출발한다고 생각하고 BFS를 돌리면서 공기와 치지를 접촉시켜 보면 됩니다.

 

1. 공기는 이미 방문했던 곳을 다시 방문할 필요가 없다

2. 공기가 접촉한 적이 없는 치즈를 만나면 그곳을 한 시간 후 녹을 치즈로 바꾸고('c') 방문 체크를 합니다.

-> 그리고 한 시간 후 공기는 이 위치에서 다시 BFS를 진행하도록 임시 큐에 해당 좌표를 넣습니다.

-> 치즈가 녹으면 결국 그곳엔 공기가 생김 

 

 

<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
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
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
#include <cstdlib>
using namespace std;
 
#define X first
#define Y second
 
int dx[4= {0-101}; //0 == right, 1 == up, 2 == left, 3 == down
int dy[4= {10-10};
 
int n, m;
 
int cheeze[100][100];
bool visited[100][100];
void AirBFS() {
    queue<pair<intint> > Q;
    Q.push({ 00 });
    visited[0][0= true;
    int time = 0// 걸린 시간
    int last_cnt = 0//마지막 녹기 한 시간 전에 남아있는 치즈 조각의 수 
    while (true) {
        queue<pair<intint> > temp;
        bool flag = false//한 시간 후 녹일 치즈가 있다면 true
        int cnt = 0// 한 시간 후 녹일 치즈의 개수
        while (!Q.empty()) {
            auto cur = Q.front(); Q.pop();
            for (int dir = 0; dir < 4; dir++) {
                int nx = cur.X + dx[dir];
                int ny = cur.Y + dy[dir];
                if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                if (visited[nx][ny] || cheeze[nx][ny] == 'c'continue// 이미 방문했거나 치즈가 공기에 접촉했으면 무시
                if (cheeze[nx][ny] == 1) { // 공기에 접촉하지 않은 치즈이면
                    flag = true
                    cheeze[nx][ny] = 'c'// 한 시간 후 치즈를 녹인다.
                    cnt++// 한 시간 후 녹일 치즈의 개수 증가
                    temp.push({ nx, ny }); // 공기는 한 시간 후 녹을 치즈의 위치에서 다시 시작
                    visited[nx][ny] = true;
                }
                else { // 빈 공간이면 그냥 이동
                    Q.push({ nx, ny });
                    visited[nx][ny] = true;
                }
            }
        }
        if (!flag) { //한 시간 후 녹일 치즈가 없다면
            cout << time << '\n' << last_cnt;
            break;
        }
        last_cnt = cnt; //가장 최근에 녹인 치즈의 개수
        time++// 한 시간 뒤
        Q = temp;
    }
}
 
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> cheeze[i][j];
        }
    }
    AirBFS();
    
    return 0;
}
 
 
cs

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 12100번] 2048(Easy)  (0) 2022.01.05
[백준 18808번] 스티커 붙이기  (0) 2022.01.05
[백준 15683번] 감시  (1) 2022.01.04
[백준 1987번] 알파벳  (0) 2022.01.03
[백준 18809번] Gaaaaaaaaaarden  (0) 2022.01.02
반응형

문제 링크: https://www.acmicpc.net/problem/15683

 

15683번: 감시

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감

www.acmicpc.net

<문제 풀이> 시뮬레이션

1번 cctv부터 n번 cctv까지 한 번씩 회전시켜보면서 모든 경우의 수를 다 해보면 되는 완전 탐색 문제입니다.

 

문제는 방향을 어떻게 처리할까 인데 각 CCTV의 방향을 분리해서 생각해보면 쉽게 문제를 해결할 수 있습니다.

 

int dx[4= {0-101}; //0 == right, 1 == up, 2 == left, 3 == down
int dy[4= {10-10};
 
dfs, bfs에서 위와 같이 4방향을 나타내는데 각 인덱스의 의미는 아래와 같습니다.
0번 인덱스는 오른쪽 방향
1번 인덱스는 위쪽 방향
2번 인덱스는 왼쪽 방향
3번 인덱스는 아래쪽 방향
 
 

 

이제 cctv로 방향을 표현해보겠습니다
1번 2번 3번 4번 5번

1번 cctv : right ( 0 index)

2번 cctv: left  + right (2 index + 0 index)

3번 cctv: up + right (1 index + 0 index)

4번 cctv: left + up + right (2 index + 1 index + 0 index)

5번 cctv: down + left + up + right (3 index + 2 index + 1 index + 0 index)

 

이제 cctv로 감시구역을 체크할 때 cctv의 방향을 분리해서 한 방향씩 검사를 해보면 됩니다.

그리고 회전할 때는 방향 인덱스의 값을 +1 해주면 끝입니다. 

/*dir 1증가하면 90도 회전*/
        if (cctv[x][y] == 1) {
            check(x, y, dir); //dir == 0 일때 right
        }
        else if (cctv[x][y] == 2) { 
            check(x, y, dir); //dir == 0 일때 right
            check(x, y, dir + 2); //dir == 0 일때 left
 
        }
        else if (cctv[x][y] == 3) {
            check(x, y, dir); //dir == 0 일때 right
            check(x, y, dir + 1); //dir == 0 일때 up
        }
        else if (cctv[x][y] == 4) {
            check(x, y, dir); //dir == 0 일때 right
            check(x, y, dir + 1); //dir == 0 일때 up
            check(x, y, dir + 2); //dir == 0 일때 left
 
        }
        else if (cctv[x][y] == 5) {
            check(x, y, dir); //dir == 0 일때 right
            check(x, y, dir + 1); //dir == 0 일때 up
            check(x, y, dir + 2); //dir == 0 일때 left
            check(x, y, dir + 3); //dir == 0 일때 down

 

        }
        solve(idx + 1); //다음 cctv 회전시키기
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                cctv[i][j] = backup[i][j];
            }
        }

 

 

 

 

<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
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
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
#include <cstdlib>
using namespace std;
 
int dx[4= {0-101}; //0 == right, 1 == up, 2 == left, 3 == down
int dy[4= {10-10};
 
int N, M;
int cctv[8][8]; // 0 빈칸, 1 ~ 5 cctv, 6 벽
vector<pair<intint> > cctv_pos;
int res = 64;
 
 
//x,y에 위치한 cctv가 dir방향을 감시
void check(int x, int y, int dir) {
    dir %= 4//가능한 감시방향 right, up, left, down (0 ~ 3)
    while (true) {
        int nx = x + dx[dir];
        int ny = y + dy[dir];
        x = nx;
        y = ny;
        if (nx < 0 || ny < 0 || nx >= N || ny >= M)return;
        if (cctv[nx][ny] == 6return;
        if (cctv[nx][ny] != 0continue;
        cctv[nx][ny] = '#';
    }
}
 
 
//idx번째 cctv를 회전
void solve(int idx) {
    int cctv_cnt = cctv_pos.size();
    if (idx == cctv_cnt) { //모든 cctv를 다 확인했을 때
        int temp_res = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (cctv[i][j] == 0) temp_res++;
            }
        }
        res = min(res, temp_res);
        return;
    }
    int x = cctv_pos[idx].first;
    int y = cctv_pos[idx].second;
    int backup[8][8];
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            backup[i][j] = cctv[i][j];
        }
    }
    for (int dir = 0; dir < 4; dir++) { //4번까지 회전시켜본다
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                backup[i][j] = cctv[i][j];
            }
        }
        /*dir 1증가하면 90도 회전*/
        if (cctv[x][y] == 1) {
            check(x, y, dir); //dir == 0 일때 right
        }
        else if (cctv[x][y] == 2) { 
            check(x, y, dir); //dir == 0 일때 right
            check(x, y, dir + 2); //dir == 0 일때 left
 
        }
        else if (cctv[x][y] == 3) {
            check(x, y, dir); //dir == 0 일때 right
            check(x, y, dir + 1); //dir == 0 일때 up
        }
        else if (cctv[x][y] == 4) {
            check(x, y, dir); //dir == 0 일때 right
            check(x, y, dir + 1); //dir == 0 일때 up
            check(x, y, dir + 2); //dir == 0 일때 left
 
        }
        else if (cctv[x][y] == 5) {
            check(x, y, dir); //dir == 0 일때 right
            check(x, y, dir + 1); //dir == 0 일때 up
            check(x, y, dir + 2); //dir == 0 일때 left
            check(x, y, dir + 3); //dir == 0 일때 down
        }
        solve(idx + 1); //다음 cctv 회전시키기
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                cctv[i][j] = backup[i][j];
            }
        }
    }
}
 
 
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> cctv[i][j];
            if (cctv[i][j] >= 1 && cctv[i][j] <= 5) {
                cctv_pos.push_back({ i, j });     
            }
        }
    }
    solve(0);
    cout << res;
    
    return 0;
}
 
 
cs

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 18808번] 스티커 붙이기  (0) 2022.01.05
[백준 2636번] 치즈  (0) 2022.01.05
[백준 1987번] 알파벳  (0) 2022.01.03
[백준 18809번] Gaaaaaaaaaarden  (0) 2022.01.02
[백준 1799번] 비숍  (0) 2021.12.31
반응형

문제 링크: https://www.acmicpc.net/problem/1987

 

1987번: 알파벳

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

www.acmicpc.net

<문제 풀이> DFS, 백트랙킹

DFS로 갈 수 있는 최장 거리를 구하면 되는데 방문한 좌표로 방문 체크를 하는게 아니라 알파벳 사용여부로 방문체크를  해야 된다.


visited[26];

->알파벳 'A' ~  'Z' 각각에 'A'를 빼주면 0 ~ 25의 값에 대응시킬 수 있다

 

 

<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
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
#include <cstdlib>
using namespace std;
 
char board[20][20];
 
int R, C;
 
bool visited[26]; // A ~ Z ( 0 ~ 25)
int dx[4= {001-1};
int dy[4= {1-100};
int res = 1;
void dfs(int x, int y, int depth) {
    for (int dir = 0; dir < 4; dir++) {
        int nx = x + dx[dir];
        int ny = y + dy[dir];
        if (nx < 0 || ny < 0 || nx >= R || ny >= C)continue;
        if (visited[board[nx][ny] - 'A'])continue;
        visited[board[nx][ny] - 'A'= true;
        res = max(res, depth + 1);
        dfs(nx, ny, depth + 1);
        visited[board[nx][ny] - 'A'= false;
    }
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    cin >> R >> C;
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            cin >> board[i][j];
        }
    }
    visited[board[0][0- 'A'= true;
    dfs(001);
 
    cout << res;
    return 0;
}
 
 
cs

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 2636번] 치즈  (0) 2022.01.05
[백준 15683번] 감시  (1) 2022.01.04
[백준 18809번] Gaaaaaaaaaarden  (0) 2022.01.02
[백준 1799번] 비숍  (0) 2021.12.31
[백준 1941번] 소문난 칠공주  (0) 2021.12.31
반응형

문제 링크: https://www.acmicpc.net/problem/18809

 

18809번: Gaaaaaaaaaarden

첫째 줄에 정원의 행의 개수와 열의 개수를 나타내는 N(2 ≤ N ≤ 50)과 M(2 ≤ M ≤ 50), 그리고 초록색 배양액의 개수 G(1 ≤ G ≤ 5)와 빨간색 배양액의 개수 R(1 ≤ R ≤ 5)이 한 칸의 빈칸을 사이에 두

www.acmicpc.net

<문제 풀이> 백트랙킹

1. 배양액을 뿌릴 수 있는 땅에 대해서 같은 것이 있는 순열(RRRGG...)을 구한다.

2. 뽑은 수열에 대해서 큐 두 개를 준비해서 빨간색 배양액, 초록색 배양액을 동시에 BFS를 진행한다.

-> 큐에는 항상 같은 레벨(같은 초)의 좌표가 들어간다.

-> BFS를 진행할 때 매 초마다  빨간색 배양액과 초록색 배양액이 동일한 시간에 만나는지 체크

-> 구현상 큐에는 꽃이 피어난 좌표도 들어갈 수 있으므로 현재 좌표가 꽃이 피어난 좌표이면 무시

 

<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
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
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
#include <cstdlib>
using namespace std;
 
#define X first
#define Y second
 
int dx[4= {0 , 01-1};
int dy[4= { 1-100 };
 
int N, M, G, R;
int G_temp, R_temp;
int board[50][50];
int backup[50][50]; //board 백업용
int visited[50][50]; //배양액 방문 체크 -> 1 == R, 2 == G
int R_visited[50][50]; //R배양액 BFS 방문 체크
int G_visited[50][50]; //G배양액 BFS 방문 체크
int res = 0// 꽃의 최대 개수
 
 
//R배양액, G배양액 퍼트리기
void BFS() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            backup[i][j] = board[i][j]; //board 배열을 다시 사용하기 위해 백업
        }
    }
    queue<pair<intint> > red, green;
 
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (visited[i][j] == 1) { //R 배양액이면
                red.push({ i, j });
                R_visited[i][j] = true;
            }
            else if (visited[i][j] == 2) { // G 배양액이면
                green.push({ i, j });
                G_visited[i][j] = true;
            }
        }
    }
 
    int cnt = 0//꽃의 개수
    while (!red.empty() || !green.empty()) {
 
        int red_size = red.size();
        for (int i = 0; i < red_size; i++) {
            auto cur = red.front(); red.pop();
            if (board[cur.X][cur.Y] == 3continue//만약 꽃이 피어난 곳이면 무시
            for (int dir = 0; dir < 4; dir++) {
                int nx = cur.X + dx[dir];
                int ny = cur.Y + dy[dir];
                if (nx < 0 || ny < 0 || nx >= N || ny >= M)continue;
                if (R_visited[nx][ny] || board[nx][ny] == 0)continue//방문했거나 호수이면 무시
                if (board[nx][ny] == 3)continue// 꽃이 피어난 곳은 무시
                if (G_visited[nx][ny] && G_visited[nx][ny] != R_visited[cur.X][cur.Y] + 1)continue//배양액은 서로 다른 곳에 뿌려져야한다.
                else if (G_visited[nx][ny] && G_visited[nx][ny] == R_visited[cur.X][cur.Y] + 1) {//만약 동일한 시간에 두 배양액이 합쳐지면
                    board[nx][ny] = 3;  //꽃이 피어난다.
                    cnt++;
                    R_visited[nx][ny] = R_visited[cur.X][cur.Y] + 1;
                    continue;
                }
                R_visited[nx][ny] = R_visited[cur.X][cur.Y] + 1;
                red.push({ nx, ny });
            }
        }
 
        int green_size = green.size();
        for (int i = 0; i < green_size; i++) {
            auto cur = green.front(); green.pop();
            if (board[cur.X][cur.Y] == 3continue//만약 꽃이 피어난 곳이면 무시
            for (int dir = 0; dir < 4; dir++) {
                int nx = cur.X + dx[dir];
                int ny = cur.Y + dy[dir];
                if (nx < 0 || ny < 0 || nx >= N || ny >= M)continue;
                if (G_visited[nx][ny] || board[nx][ny] == 0)continue//방문했거나 호수이면 무시
                if (board[nx][ny] == 3)continue// 꽃이 피어난 곳은 무시
                if (R_visited[nx][ny] && R_visited[nx][ny] != G_visited[cur.X][cur.Y] + 1)continue//배양액은 서로 다른 곳에 뿌려져야한다.
                else if (R_visited[nx][ny] && R_visited[nx][ny] == G_visited[cur.X][cur.Y] + 1) {//만약 동일한 시간에 두 배양액이 합쳐지면
                    board[nx][ny] = 3;  //꽃이 피어난다.
                    cnt++;
                    G_visited[nx][ny] = G_visited[cur.X][cur.Y] + 1;
                    continue;
                }
                G_visited[nx][ny] = G_visited[cur.X][cur.Y] + 1;
                green.push({ nx, ny });
            }
        }
    }
 
    res = max(res, cnt); //최대 꽃의 개수 
 
    /*초기화*/
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            board[i][j] = backup[i][j];
            R_visited[i][j] = 0;
            G_visited[i][j] = 0;
        }
    }
}
 
//N*N 격자에서 초록색 배양액 G개, 빨간색 배양액 R개를 뽑는 조합
void dfs(int cur, int k) {
    if (k == G + R) { //초록색 배양액 G개, 빨간색 배양액 R개를 뿌렸으면
        BFS();
        return;
    }
    for (int i = cur + 1; i < N * M; i++) {
        int x = i / M;
        int y = i % M;
        if (board[x][y] == 2) { // 배양액을 뿌릴 수 있으면
            if (R_temp != 0) { // R 배양액을 다 못뿌렸으면
                R_temp--;
                visited[x][y] = 1;
                dfs(i, k + 1);
                visited[x][y] = 0;
                R_temp++;
            }
            if (G_temp != 0) { // G 배양액을 다 못뿌렸으면 
                G_temp--;
                visited[x][y] = 2;
                dfs(i, k + 1);
                visited[x][y] = 0;
                G_temp++;
            }
        }
    }
}
 
 
 
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    cin >> N >> M >> G >> R;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> board[i][j];
        }
    }
    G_temp = G;
    R_temp = R;
    dfs(-10);
    cout << res;
    return 0;
}
 
 
cs

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 15683번] 감시  (1) 2022.01.04
[백준 1987번] 알파벳  (0) 2022.01.03
[백준 1799번] 비숍  (0) 2021.12.31
[백준 1941번] 소문난 칠공주  (0) 2021.12.31
[백준 16987번] 계란으로 계란치기  (0) 2021.12.30
반응형

문제 링크: https://www.acmicpc.net/problem/1799

 

1799번: 비숍

첫째 줄에 체스판의 크기가 주어진다. 체스판의 크기는 10이하의 자연수이다. 둘째 줄부터 아래의 예와 같이 체스판의 각 칸에 비숍을 놓을 수 있는지 없는지에 대한 정보가 체스판 한 줄 단위로

www.acmicpc.net

 

 

<문제 풀이> 백트랙킹

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

 

9663번: N-Queen

N-Queen 문제는 크기가 N × N인 체스판 위에 퀸 N개를 서로 공격할 수 없게 놓는 문제이다. N이 주어졌을 때, 퀸을 놓는 방법의 수를 구하는 프로그램을 작성하시오.

www.acmicpc.net

이문제는 9663번 문제와 비슷하게 접근하면 되는데 핵심은 다음 세 가지입니다.

1. 체스판은 흑색, 백색으로 나누어져 있고, 각 비숍은 다른 색깔에 위치한 비숍을 공격할 수 없다.

 

2. 2차원 배열에서 조합

 

3. 2차원 배열에서 윗 방향 대각선은 X + Y, 아랫 방향 대각선은 X - Y + N으로 나타낼 수 있다.

 

흰색, 검은색 판을 구분하는 방법은 2차원 배열에서 x + y 값을 보면 같은 대각선에 존재하면 x +  y 값이 같은 걸 알 수 있습니다. 

 

 

 

 

<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
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
#include <cstdlib>
using namespace std;
 
int board[10][10];
bool visited1[20]; //  / 대각선
bool visited2[20]; //  \ 대각선
int n;
int res = 0;
void dfs(int k, int cnt, bool color) { //color == true 흰색, color == false 검은색
    if (k >= n * n) {
        return;
    }
    for (int i = k; i < n * n; i++) {
        int x = i / n;
        int y = i % n;
        if (color && (x + y) % 2 != 0) {//흰색이 아니면
            continue;
        }
        else if(!color && (x + y) % 2 == 0){//검은색이 아니면
            continue;
        }
        if (board[x][y] == 0continue;
        if (visited1[x + y])continue;
        if (visited2[x - y + n])continue;
        visited1[x + y] = true;
        visited2[x - y + n] = true;
        res = max(res, cnt + 1);
        dfs(i + 1 , cnt + 1, color);
        visited1[x + y] = false;
        visited2[x - y + n] = false;
        
    }
}
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
  
    cin >> n;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> board[i][j];
        }
    }
    dfs(00true);
    int temp = res;
    res = 0;
    dfs(10false);
    cout << temp + res;
    return 0;
}
 
 
cs

 

반응형
반응형

문제 링크: https://www.acmicpc.net/problem/1941

 

1941번: 소문난 칠공주

총 25명의 여학생들로 이루어진 여학생반은 5×5의 정사각형 격자 형태로 자리가 배치되었고, 얼마 지나지 않아 이다솜과 임도연이라는 두 학생이 두각을 나타내며 다른 학생들을 휘어잡기 시작

www.acmicpc.net

<문제 풀이> 백트랙킹

5X5 격자에서 7자리를 뽑아서(2차원 배열에서 조합) BFS로 연결 여부 확인 + S의 개수가 4 이상인지 확인하면 됩니다.

 

2차원 배열 조합

 for (int i = s; i < 25; i++) {
        int x = i / 5;
        int y = i % 5;
        res[x][y] = 1;
        dfs(i + 1, k + 1);
        res[x][y] = 0;
    }

<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
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
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
#include <cstdlib>
using namespace std;
 
#define X first
#define Y second
 
int res[5][5];
int dx[4= {001-1};
int dy[4= { -1100 };
bool visited[5][5];
vector<vector<char> > v(5);
int cnt = 0;
 
void dfs(int s, int k) {
    if (k == 7) {
        int temp = 0;
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                if (res[i][j] == 1 && v[i][j] == 'S') {
                    temp++;
                }
            }
        }
        if (temp >= 4) {
 
            int connected = 0;
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 5; j++) {
                    if (res[i][j] == 1 && !visited[i][j]) {
                        queue<pair<intint> > Q;
                        Q.push({ i, j });
                        visited[i][j] = true;
                        while (!Q.empty()) {
                            auto cur = Q.front(); Q.pop();
                            for (int dir = 0; dir < 4; dir++) {
                                int nx = cur.X + dx[dir];
                                int ny = cur.Y + dy[dir];
                                if (nx < 0 || ny < 0 || nx >= 5 || ny >= 5)continue;
                                if (visited[nx][ny] || res[nx][ny] == 0)continue;
                                Q.push({ nx, ny });
                                visited[nx][ny] = true;
                            }
                        }
                        connected++;
                    }
                }
            }
            if (connected == 1) cnt++;
        }
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                visited[i][j] = 0;
            }
        }
        return;
    }
 
    for (int i = s; i < 25; i++) {
        int x = i / 5;
        int y = i % 5;
        res[x][y] = 1;
        dfs(i + 1, k + 1);
        res[x][y] = 0;
    }
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
   
    for (int i = 0; i < 5; i++) {
        string s; cin >> s;
        int s_len = s.length();
        v[i].resize(5);
        for (int j = 0; j < s_len; j++) {
            v[i][j] = s[j];
        }
    } 
    dfs(00);
    cout << cnt;
   
 
    return 0;
}
 
cs

 

반응형
반응형

문제 링크: https://www.acmicpc.net/problem/16987

 

16987번: 계란으로 계란치기

원래 프로그래머의 기본 소양은 팔굽혀펴기를 단 한 개도 할 수 없는 것이라고 하지만 인범이는 3대 500을 넘기는 몇 안되는 프로그래머 중 한 명이다. 인범이는 BOJ에서 틀린 제출을 할 때마다 턱

www.acmicpc.net

<문제 풀이>

  1. 가장 왼쪽의 계란을 든다.
  2. 손에 들고 있는 계란으로 깨지지 않은 다른 계란 중에서 하나를 친다. 단, 손에 든 계란이 깨졌거나 깨지지 않은 다른 계란이 없으면 치지 않고 넘어간다. 이후 손에 든 계란을 원래 자리에 내려놓고 3번 과정을 진행한다.
  3. 가장 최근에 든 계란의 한 칸 오른쪽 계란을 손에 들고 2번 과정을 다시 진행한다. 단, 가장 최근에 든 계란이 가장 오른쪽에 위치한 계란일 경우 계란을 치는 과정을 종료한다.

문제 조건을 그대로 dfs로 구현하면 된다.

<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
54
55
56
57
58
59
60
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
#include <cstdlib>
using namespace std;
 
#define S first
#define W second
 
int n;
vector<pair<intint> > egg;
int res = 0;
void dfs(int idx) { //idx번째 계란을 든다
    if (idx >= n) { //가장 최근에 든 계란이 가장 오른쪽에 위치한 경우
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if (egg[i].S <= 0) cnt++//깨진 계란 카운트
        }
        res = max(res, cnt);
        return;
    }
    bool flag = false//idx번째 계란으로 다른 계란을 쳤는지 여부
    for (int i = 0; i < n; i++) {
        if (i == idx) continue// 자기 자신 무시
        if (egg[idx].S > 0 && egg[i].S > 0) { // 계란을 칠 수 있으면
            egg[idx].S -= egg[i].W;
            egg[i].S -= egg[idx].W;
            flag = true;
            dfs(idx + 1);
            egg[idx].S += egg[i].W;
            egg[i].S += egg[idx].W;
        }
    }
    if(!flag) dfs(idx + 1); //계란을 칠 수 없으면 넘어간다.
 
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    cin >> n;
 
    for (int i = 0; i < n; i++) {
        int s, w;
        cin >> s >> w;
        egg.push_back({ s,w });
    }
    dfs(0);
    cout << res;
    return 0;
}
 
cs

 

반응형

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 1799번] 비숍  (0) 2021.12.31
[백준 1941번] 소문난 칠공주  (0) 2021.12.31
[백준 2448번] 별 찍기 - 11  (0) 2021.12.27
[백준 2447번] 별 찍기 - 10  (0) 2021.12.27
[백준 1992번] 쿼드트리  (0) 2021.12.27
반응형

문제 링크: https://www.acmicpc.net/problem/2448

 

2448번: 별 찍기 - 11

첫째 줄에 N이 주어진다. N은 항상 3×2k 수이다. (3, 6, 12, 24, 48, ...) (0 ≤ k ≤ 10, k는 정수)

www.acmicpc.net

<문제 풀이> 재귀

위 그림처럼 3등분을 계속해서 n == 3일 때 (x, y)을 기준으로 별을 배열에 업데이트하면 됩니다.

 

 

<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
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <utility>
#include <climits>
#include <cmath>
#include <deque>
 
using namespace std;
 
char board[3072][6144];

//x,y에서 시작해서 높이가 n인 별 찍기
void solve(int x, int y, int n) {
    if (n == 3) {
        board[x][y] = '*';
        board[x+1][y-1] = '*';
        board[x + 1][y + 1] = '*';
        board[x + 2][y - 2] = '*';
        board[x + 2][y - 1] = '*';
        board[x + 2][y] = '*';
        board[x + 2][y + 1] = '*';
        board[x + 2][y + 2] = '*';
        return;
    }
    solve(x, y, n / 2);
    solve(x + n / 2, y - n / 2, n / 2);
    solve(x + n / 2, y + n / 2, n / 2);
 
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n; cin >> n;
    fill(&board[0][0], &board[3071][6144], ' ');
    solve(0, n - 1, n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 2*n; j++) {
            cout << board[i][j];
        }
        cout << '\n';
    }
    return 0;
}
 
cs

 

 

반응형

+ Recent posts