반응형

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

 

16985번: Maaaaaaaaaze

첫째 줄부터 25줄에 걸쳐 판이 주어진다. 각 판은 5줄에 걸쳐 주어지며 각 줄에는 5개의 숫자가 빈칸을 사이에 두고 주어진다. 0은 참가자가 들어갈 수 없는 칸, 1은 참가자가 들어갈 수 있는 칸을

www.acmicpc.net

<문제 풀이> 시뮬레이션, BFS, 조합, next_permutation

1. 각 판 회전시키기 구현

 

2. next_permutation을 이용해서 각 판 쌓기 구현

 

3. BFS로 시작점부터 도착점까지 최단거리 구하기

-> 이때 큐브의 입구는 정육면체에서 참가자가 임의로 선택한 꼭짓점에 위치한 칸이고 출구는 입구와 면을 공유하지 않는 꼭짓점에 위치한 칸이다.

-> 시작점을 0, 0, 0 / 도착점을 4, 4, 4로 고정해도 되는 이유는 시작점과 도착점을 고정시키고 판을 잘 회전시키고 잘 쌓으면 다른 꼭짓점에서 출발시킨 것과 동일하다.

 

4. 판을 회전시키는 모든 경우에 대해서 진행

 

<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
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
 
int maze[5][5][5]; //판을 쌓은 미로
int board[5][5][5]; //5개의 판
int dist[5][5][5];
const int dx[6= {00001-1};
const int dy[6= {001-100};
const int dz[6= {1-10000};
 
int res = 125;
 
vector<int> v{ 01234 }; //쌓일 판의 순서
 
class pos {
public:
    int z;
    int x;
    int y;
    pos(int z, int x, int y) : z(z), x(x), y(y) {
    }
};
 
void stackMaze() {
    for (int z = 0; z < 5; z++) {
        for (int x = 0; x < 5; x++) {
            for (int y = 0; y < 5; y++) {
                maze[z][x][y] = board[v[z]][x][y];
            }
        }
    }
 
}
 
void init() {
    for (int z = 0; z < 5; z++) {
        for (int x = 0; x < 5; x++) {
            for (int y = 0; y < 5; y++) {
                dist[z][x][y] = 0;
            }
        }
    }
}
 
void rotate(int z) {
    int temp[5][5];
    for (int x = 0; x < 5; x++) {
        for (int y = 0; y < 5; y++) {
            temp[x][y] = board[z][x][y];
        }
    }
    for (int x = 0; x < 5; x++) {
        for (int y = 0; y < 5; y++) {
            board[z][y][4 - x] = temp[x][y];
        }
    }
}
 
int bfs() {
    if (maze[0][0][0== 0 || maze[4][4][4== 0return -1//입구 혹은 출구가 막혀있을 경우
    pos p(000);
    queue<pos> Q;
    Q.push(p);
    dist[p.z][p.x][p.y] = 1;
    while (!Q.empty()) {
        auto cur = Q.front(); Q.pop();
        for (int dir = 0; dir < 6; dir++) {
            int nz = cur.z + dz[dir];
            int nx = cur.x + dx[dir];
            int ny = cur.y + dy[dir];
            if (nz < 0 || nx < 0 || ny < 0 || nz >= 5 || nx >= 5 || ny >= 5)continue;
            if (maze[nz][nx][ny] == 0 || dist[nz][nx][ny]) continue;
            Q.push({ nz, nx,ny });
            dist[nz][nx][ny] = dist[cur.z][cur.x][cur.y] + 1;
            if (nz == 4 && nx == 4 && ny == 4return dist[nz][nx][ny];
        }
    }
    return -1;
}
 
void solve(int k) {
    if (k == 5return;
    for (int i = 0; i < 4; i++) { //k번째 판을 4번까지 회전시켜본다
        rotate(k); 
        do {
            stackMaze(); 
            int ret = bfs();
            if (ret != -1) res = min(res, ret);
            init();        
        } while (next_permutation(v.begin(), v.end())); //판을 쌓는 순열
        for (int m = 0; m < 5; m++)v[m] = m;
        solve(k + 1); // k+1번째 판을 4번까지 회전시켜본다.
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    
    for (int z = 0; z < 5; z++) {
        for (int x = 0; x < 5; x++) {
            for (int y = 0; y < 5; y++) {
                cin >> board[z][x][y];
            }
        }
    }
    solve(0);
    if (res == 125cout << "-1";
    else cout << res - 1;
 
 
    return 0;
}
cs

 

 

 

반응형

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

[백준 3190번] 뱀  (0) 2022.01.19
[백준 2638번] 치즈  (0) 2022.01.17
[백준 14499번] 주사위 굴리기  (0) 2022.01.15
[백준 6443번] 애너그램  (0) 2022.01.14
[백준 11559번] Puyo Puyo  (0) 2022.01.13
반응형

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

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x, y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지

www.acmicpc.net

<문제 풀이> 시뮬레이션

    2

4  1  3

    5

    6

문제에서 나온 주사위를 배열로 표현하면 dice[1] == 윗면, dice[6] == 바닥

 

동쪽으로 굴렸을 때

    2

6   4  1

    5

    3

 

서쪽으로 굴렸을 때

    2

1   3  6

    5

    4

 

북쪽으로 굴렸을 때

    1

4  5  3

    6

    2

 

님쪽으로 굴렸을 때

    6

4  2  3

    1

    5

 

굴리기 전 배열의 값을 temp에 저장해놓고 위에 바뀐 주사위의 상태를 기록하면 됩니다.

배열의 값은 변하지만, 인덱스의 의미는 그대로 주사위의 윗면, 바닥면, 옆면을 의미합니다.

 

<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
#include <iostream>
using namespace std;
 
#define EAST 1
#define WEST 2
#define NORTH 3
#define SOUTH 4
 
int N, M, x, y, k;
int board[20][20];
int dice[7]; // 바닥 index = 6
const int dx[5= { 000-11 }; // (1, 2, 3, 4) == (동, 서, 북, 남)
const int dy[5= { 01,-100 };
 
void rotateDice(int dir) {
    int temp[7];
    for (int i = 0; i < 7; i++) temp[i] = dice[i];
    if (dir == EAST) {
        dice[1= temp[4];
        dice[3= temp[1];
        dice[4= temp[6];
        dice[6= temp[3];
    }
    else if (dir == WEST) {
        dice[1= temp[3];
        dice[3= temp[6];
        dice[4= temp[1];
        dice[6= temp[4];
    }
    else if (dir == NORTH) {
        dice[1= temp[5];
        dice[2= temp[1];
        dice[5= temp[6];
        dice[6= temp[2];
    }
    else if (dir == SOUTH) {
        dice[1= temp[2];
        dice[2= temp[6];
        dice[5= temp[1];
        dice[6= temp[5];
    }
}
 
void move(int dir) {
    int nx = x + dx[dir];
    int ny = y + dy[dir];
    if (nx < 0 || ny < 0 || nx >= N || ny >= M) return// 주사위는 지도의 바깥으로 이동시킬 수 없다.
    rotateDice(dir); // 주사위 이동
    if (board[nx][ny] == 0) {//이동한 칸에 쓰여 있는 수가 0이면
        board[nx][ny] = dice[6]; //주사의위 바닥면에 쓰여 있는 수가 칸에 복사된다.
    }
    else {
        dice[6= board[nx][ny]; //칸에 쓰여 있는 수가 주사위의 바닥면으로 복사되며,
        board[nx][ny] = 0;  // 칸에 쓰여 있는 수는 0이 된다.
    }
    cout << dice[1]<<'\n';
    x = nx;
    y = ny;
}
 
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    
    cin >> N >> M >> x >> y >> k;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin>>board[i][j];
        }
    }
    for (int i = 0; i < k; i++) {
        int command; cin >> command;
        move(command);
    }
    return 0;
}
cs

 

반응형

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

[백준 2638번] 치즈  (0) 2022.01.17
[백준 16985번] Maaaaaaaaaze  (0) 2022.01.16
[백준 6443번] 애너그램  (0) 2022.01.14
[백준 11559번] Puyo Puyo  (0) 2022.01.13
[백준 15686번] 치킨 배달  (0) 2022.01.09
반응형

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

 

6443번: 애너그램

첫째 줄에 단어의 개수 N 이, 둘째 줄부터 N개의 영단어가 들어온다. 영단어는 소문자로 이루어져 있다. 단어의 길이는 20보다 작거나 같고, 애너그램의 수가 100,000개 이하인 단어만 입력으로 주

www.acmicpc.net

<문제 풀이>

각 알파벳의 개수를 구해서 방문 체크할 때 해당 알파벳이 현재까지 몇 개를 사용했는지 카운트를 해주면 됩니다.

 

<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>
#include <string>
using namespace std;
 
int arr[26];
int visited[26];
char res[20];
int len;
void dfs(int k) {
    if (k == len) {
        for (int i = 0; i < len; i++) {
            cout << res[i];
        }
        cout << '\n';
        return;
    }
    for (int i = 0; i < 26; i++) {
        if (arr[i] == 0continue;
        if (visited[i] == arr[i])continue;
        res[k] = i + 'a';
        visited[i]++;
        dfs(k + 1);
        visited[i]--;
    }
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
 
    int test_case;
    cin >> test_case;
    for (int i = 0; i < test_case; i++) {
        string s;
        cin >> s;
        len = s.length();
        for (int j = 0; j < len; j++) {
            arr[s[j]-'a']++;
        }
        dfs(0);
        fill(arr, arr + 260);
        fill(visited, visited + 260);
    }
 
    return 0;
}
cs

 

반응형

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

[백준 16985번] Maaaaaaaaaze  (0) 2022.01.16
[백준 14499번] 주사위 굴리기  (0) 2022.01.15
[백준 11559번] Puyo Puyo  (0) 2022.01.13
[백준 15686번] 치킨 배달  (0) 2022.01.09
[백준 12094번] 2048 (Hard)  (0) 2022.01.08
반응형

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

 

11559번: Puyo Puyo

총 12개의 줄에 필드의 정보가 주어지며, 각 줄에는 6개의 문자가 있다. 이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다. R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.

www.acmicpc.net

<문제 풀이> BFS, 시뮬레이션

1. BFS로 한 뿌요와 4방향으로 연결된 동일한 뿌요의 개수를 센다 

2. 만약 동일한 뿌요의 개수가 4개 이상이면 해당 뿌요를 터트린다.

3. 모든 뿌요를 떨어뜨린다.

 

만약 터트릴 뿌요가 없으면 종료

 

 

 

<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
#include <iostream>
#include <queue>
#include <utility>
using namespace std;
 
#define X first
#define Y second
 
const int dx[4= { 001-1 };
const int dy[4= { 1-100 };
 
const int r = 12;
const int c = 6;
 
char board[r][c];
bool visited[r][c];
 
void boom(int x, int y) {
    queue<pair<intint > > Q;
    Q.push({ x, y });
    char target = board[x][y];
    board[x][y] = '.';
    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 >= r || ny >= c)continue;
            if (board[nx][ny] != target) continue;
            board[nx][ny] = '.';
            Q.push({ nx, ny });
        }
    }
}
 
void fall() {
    for (int y = 0; y < c; y++) {
        char moved[r];
        int idx = 0;
        for (int x = r - 1; x >= 0; x--) {
            if (board[x][y] != '.') {
                moved[idx++= board[x][y];
            }
        }
        for (int i = 0; i < idx; i++) {
            board[r - 1 - i][y] = moved[i];
        }
        for (int i = idx; i < r; i++) {
            board[r - 1 - i][y] = '.';
        }
    }
}
 
bool bfs() {
    bool ret = false;
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            if (board[i][j] != '.' && !visited[i][j]) {
                queue<pair<intint> > Q;
                Q.push({ i, j });
                visited[i][j] = true;
                int cnt = 1;
                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 >= r || ny >= c)continue;
                        if (visited[nx][ny] || board[nx][ny] != board[cur.X][cur.Y])continue;                    
                        visited[nx][ny] = true;
                        cnt++;
                        Q.push({ nx, ny });
                    }
                }
                if (cnt >= 4) { // 뿌요들이 4개 이상 모이면
                    ret = true;
                    boom(i, j);
                }
            }
        }
    }
    fill(&visited[0][0], &visited[r - 1][c], 0);
    return ret;
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            cin >> board[i][j];
        }
    }
    int res = 0;
    while (bfs()) {
        res++;
        fall();
    }
    cout << res;
    return 0;
}
cs

 

반응형

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

[백준 14499번] 주사위 굴리기  (0) 2022.01.15
[백준 6443번] 애너그램  (0) 2022.01.14
[백준 15686번] 치킨 배달  (0) 2022.01.09
[백준 12094번] 2048 (Hard)  (0) 2022.01.08
[백준 12100번] 2048(Easy)  (0) 2022.01.05
반응형

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

 

15686번: 치킨 배달

크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸

www.acmicpc.net

<문제 풀이> 시뮬레이션 + 조합

문제에서 최대 M개의 치킨집을 선택할 수 있다고 했는데 치킨집의 개수가 많을수록 치킨 거리가 더 짧아지니깐 그냥 M개의 치킨집을 뽑는 조합을 구현하면 된다.

 

 

<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
#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[50][50];
bool choose[50][50];
int N, M;
int res = 2500;
vector<pair<intint> > chicken;
vector<pair<intint> > house;
 
void dfs(int idx, int depth) {
    if (depth == M) {
        int sum = 0;
        for (auto h : house) {
            int r1 = h.first;
            int c1 = h.second;
            int chicken_dist = 2500;
            for (auto c : chicken) {
                int r2 = c.first;
                int c2 = c.second;
                if (choose[r2][c2]) {
                    int dist = abs(r1 - r2) + abs(c1 - c2);
                    chicken_dist = min(chicken_dist, dist);
                }
            }
            sum += chicken_dist;
 
        }
        res = min(res, sum);
        return;
    }
    int chicken_size = chicken.size();
    for (int i = idx; i < chicken_size; i++) {
        int r = chicken[i].first;
        int c = chicken[i].second;
        choose[r][c] = true;
        dfs(i + 1, depth + 1);
        choose[r][c] = false;
    }
}
 
 
 
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 < N; j++) {
            cin >> board[i][j];
            if (board[i][j] == 2) chicken.push_back({ i, j });
            if (board[i][j] == 1)house.push_back({ i, j });
        }
    }
    dfs(00);
 
    cout << res;
  
 
    return 0;
}
 
 
cs

 

반응형

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

[백준 6443번] 애너그램  (0) 2022.01.14
[백준 11559번] Puyo Puyo  (0) 2022.01.13
[백준 12094번] 2048 (Hard)  (0) 2022.01.08
[백준 12100번] 2048(Easy)  (0) 2022.01.05
[백준 18808번] 스티커 붙이기  (0) 2022.01.05
반응형

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

 

12094번: 2048 (Hard)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2

www.acmicpc.net

<문제 풀이> 백트랙킹

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

 

12100번: 2048 (Easy)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2

www.acmicpc.net

2048 Easy 문제에서 백트랙킹이 추가된 문제이다.

 

1. 이동 후 항상 변화가 있어야 한다. (이동 후 배열의 값이 바뀌었는지 체크)

2 4 8

2 4 8 

2 4 8

에서 left를 하면

2 4 8

2 4 8

2 4 8

변화가 없는 상태에서 계속 연산을 해봤자 의미가 없다. 

-> 최대 k 번까지 이동했을 때 최댓값을 구하고 싶은 거니깐 항상 변화가 있어야 한다.

 

2. k번 이동했을 때 현재 배열의 값으로 10번까지 이동해서 만들 수 있는 최댓값이 지금 까지 갱신한 최댓값 이하이면  더 이상 진행하지 않는다.

1번 이동했을 때 현재 배열의 값의 최대값이 2라면

10번 이동했을 때 현재 배열의 최댓값으로 만들 수 있는 수는 2048이다.

2 * 2 ^ (10 - 1) = 1024  -> ( 현재 배열의 값의 최대값 * 2^(10 - k) ) 

그런데 지금까지 갱신한 최댓값이 4096이라면

아무리 최고의 상황이 나오더라도 10번까지 이동해서 4096을 만들 수 없다

 

 

<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
161
162
163
164
165
166
167
168
169
170
171
172
173
#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 N;
int board[20][20];
bool visited[20][20];
int res = 0;
int max_res = 0;
void printBoard() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cout << board[i][j] << ' ';
        }
        cout << '\n';
    }
    cout << "\n\n";
}
 
void rotate() {
    int temp[20][20];
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            temp[i][j] = board[i][j];
        }
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            board[i][j] = temp[N - j - 1][i];
        }
    }
}
 
 
void left() {
    for (int i = 0; i < N; i++) {
        int moved[20= { 0, };
        bool combined[20= { 0, };
        int idx = 0;
        for (int j = 0; j < N; j++) {
            if (board[i][j] == 0continue;
            if (moved[idx] == 0) {
                moved[idx] = board[i][j];
            }
            else if (moved[idx] && combined[idx]) {
                moved[++idx] = board[i][j];
            }
            else if (moved[idx] == board[i][j]){
                moved[idx] *= 2;
                combined[idx++= true;
           
            }
            else {
                moved[++idx] = board[i][j];
            }
 
            
        }
        for (int j = 0; j < N; j++) {
            board[i][j] = moved[j];
        }
    }
}
 
void up() {
    rotate();
    rotate();
    rotate();
    left();
    rotate();
}
void right() {
    rotate();
    rotate();
    left();
    rotate();
    rotate();
 
}
 
void down() {
    rotate();
    left();
    rotate();
    rotate();
    rotate();
}
 
void tempToBoard(int temp[][20]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            board[i][j] = temp[i][j];
        }
    }
}
 
bool isChanged(int arr1[][20], int arr2[][20]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (arr1[i][j] != arr2[i][j]) return true;
        }
    }
    return false;
}
 
void dfs(int k) {
    int temp[20][20];
    int cur_max = 0;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            temp[i][j] = board[i][j];
            if (board[i][j] >= cur_max) cur_max = board[i][j];
        }
    }
    res = max(res, cur_max);
 
    if (k == 10return;
    if (cur_max * 1 << (10 - k) <= res) return;
 
    left();
    if (isChanged(temp, board)) {
        dfs(k + 1);
        tempToBoard(temp);
    }
    right();
    if (isChanged(temp, board)) {
        dfs(k + 1);
        tempToBoard(temp);
    }
    up();
    if (isChanged(temp, board)) {
        dfs(k + 1);
        tempToBoard(temp);
    }
    down();
    if (isChanged(temp, board)) {
        dfs(k + 1);
        tempToBoard(temp);
    }
 
 
 
 
}
 
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];
            if (board[i][j] >= max_res) max_res = board[i][j];
        }
    }
    
    dfs(0);
    cout << res;
   
    return 0;
}
 
 
cs

 

반응형

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

[백준 11559번] Puyo Puyo  (0) 2022.01.13
[백준 15686번] 치킨 배달  (0) 2022.01.09
[백준 12100번] 2048(Easy)  (0) 2022.01.05
[백준 18808번] 스티커 붙이기  (0) 2022.01.05
[백준 2636번] 치즈  (0) 2022.01.05
반응형

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

 

12100번: 2048 (Easy)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2

www.acmicpc.net

<문제 풀이> 시뮬레이션

4가지 이동방향을 구현한 뒤 DFS로 4가지 방향에 대한 모든 경우의 수를 구하면 된다.

한 가지 방향만 잘 구현하면 나머지는 비슷하기에 금방 구현할 수 있다.

 

up방향을 구현할 때 그냥 각 열에 원소를 맨 위 원소부터 시작해서 하나씩 잡고 위로 당겨보면 된다. 

 

 

<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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#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 N;
int board[20][20];
bool visited[20][20];
int res = 0;
void printBoard() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cout << board[i][j] << ' ';
        }
        cout << '\n';
    }
    cout << "\n\n";
}
 
void up() {
    for (int i = 1; i < N; i++) {
        for (int j = 0; j < N; j++) {
            for (int k = i; k >= 1; k--) {
                if (board[k][j] == 0)break;
                if (board[k - 1][j]) {
                    if (!visited[k - 1][j] && board[k-1][j] == board[k][j]) {
                        board[k - 1][j] *= 2;
                        board[k][j] = 0;
                        visited[k - 1][j] = true;
                    }
                    break;
                }
                else {
                    board[k - 1][j] = board[k][j];
                    board[k][j] = 0;
                }
            }
 
        }
    }
    fill(&visited[0][0], &visited[19][20], 0);
}
 
void down() {
    for (int i = N-2; i >=0; i--) {
        for (int j = 0; j < N; j++) {
            for (int k = i; k <= N-2; k++) {
                if (board[k][j] == 0)break;
                if (board[k + 1][j]) {
                    if (!visited[k + 1][j] && board[k + 1][j] == board[k][j]) {
                        board[k + 1][j] *= 2;
                        board[k][j] = 0;
                        visited[k + 1][j] = true;
                    }
                    break;
                }
                else {
                    board[k + 1][j] = board[k][j];
                    board[k][j] = 0;
                }
            }
 
        }
    }
    fill(&visited[0][0], &visited[19][20], 0);
}
void left() {
    for (int j = 1; j < N; j++) {
        for (int i = 0; i < N; i++) {
            for (int k = j; k >= 1; k--) {
                if (board[i][k] == 0)break;
                if (board[i][k-1]) {
                    if (!visited[i][k-1&& board[i][k-1== board[i][k]) {
                        board[i][k-1*= 2;
                        board[i][k] = 0;
                        visited[i][k-1= true;
                        
                    }
                    break;
                    
                }
                else {
                    board[i][k-1= board[i][k];
                    board[i][k] = 0;
                }
            }
        }
    }
    fill(&visited[0][0], &visited[19][20], 0);
}
 
void right() {
    for (int j = N-2; j >=0; j--) {
        for (int i = 0; i < N; i++) {
            for (int k = j; k <= N-2; k++) {
                if (board[i][k] == 0)break;
                if (board[i][k + 1]) {
                    if (!visited[i][k + 1&& board[i][k + 1== board[i][k]) {
                        board[i][k + 1*= 2;
                        board[i][k] = 0;
                        visited[i][k + 1= true;
                    }
                    break;
                }
                else {
                    board[i][k + 1= board[i][k];
                    board[i][k] = 0;
                }
            }
        }
    }
    fill(&visited[0][0], &visited[19][20], 0);
}
void dfs(int k) {
    if (k == 5) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                res = max(res, board[i][j]);             
            }
        }
        return;
    }
    int temp[20][20];
 
    for (int i = 0; i < 20; i++) {
        for (int j = 0; j < 20; j++) {
            temp[i][j] = board[i][j];
        }
    }
    up();
    dfs(k + 1);
    for (int i = 0; i < 20; i++) {
        for (int j = 0; j < 20; j++) {
            board[i][j] = temp[i][j];
        }
    }
    left();
    dfs(k + 1);
    for (int i = 0; i < 20; i++) {
        for (int j = 0; j < 20; j++) {
            board[i][j] = temp[i][j];
        }
    }
    down();
    dfs(k + 1);
    for (int i = 0; i < 20; i++) {
        for (int j = 0; j < 20; j++) {
            board[i][j] = temp[i][j];
        }
    }
    right();
    dfs(k + 1);
    for (int i = 0; i < 20; i++) {
        for (int j = 0; j < 20; j++) {
            board[i][j] = temp[i][j];
        }
    }
 
}
 
 
 
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(0);
    cout << res;
  
    return 0;
}
 
 
cs

 

 

반응형

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

[백준 15686번] 치킨 배달  (0) 2022.01.09
[백준 12094번] 2048 (Hard)  (0) 2022.01.08
[백준 18808번] 스티커 붙이기  (0) 2022.01.05
[백준 2636번] 치즈  (0) 2022.01.05
[백준 15683번] 감시  (1) 2022.01.04
반응형

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

 

18808번: 스티커 붙이기

혜윤이는 최근에 다양한 대회를 참여하면서 노트북에 붙일 수 있는 스티커들을 많이 받았다. 스티커는 아래와 같이 사각 모눈종이 위에 인쇄되어 있으며, 스티커의 각 칸은 상하좌우로 모두 연

www.acmicpc.net

<문제 풀이> 시뮬레이션

이 문제는 배열을 회전하는 것만 잘 구현하면 되는 문제이다.

 

배열을 그려서 규칙을 잘 보면 X행에 있는 모든 원소는 90도 회전하면 Y열로 이동하고,

row, col 값이 서로 바뀐다

 

/*idx 번째 스티커를 1회전*/
void rotate(int idx) {
    int temp[10][10];
    for (int x = 0; x < R[idx]; x++) {
        for (int y = 0; y < C[idx]; y++) {
            temp[x][y] = sticker[idx][x][y];
        }
    }
    swap(R[idx], C[idx]);
    for (int x = 0; x < R[idx]; x++) {
        for (int y = 0; y < C[idx]; y++) {
            sticker[idx][x][y] = temp[C[idx] - 1 - y][x];
        }
    }
}

 

배열 회전만 구현하면 나머지는 문제 조건 그대로 구현하면 끝이다.

 

 

<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
#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 N, M, K;
 
int sticker[100][10][10];
bool notebook[40][40];
int R[100];
int C[100];
 
 
/*idx 번째 스티커를 1회전*/
void rotate(int idx) {
    int temp[10][10];
    for (int x = 0; x < R[idx]; x++) {
        for (int y = 0; y < C[idx]; y++) {
            temp[x][y] = sticker[idx][x][y];
        }
    }
    swap(R[idx], C[idx]);
    for (int x = 0; x < R[idx]; x++) {
        for (int y = 0; y < C[idx]; y++) {
            sticker[idx][x][y] = temp[C[idx] - 1 - y][x];
        }
    }
}
 
/*idx번째 스티커를 붙여본다 성공 true, 실패 false*/
bool solve(int idx) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            bool flag = true;
            for (int x = 0; x < R[idx]; x++) {
                if (!flag)break;
                for (int y = 0; y <C[idx]; y++) {
                    if (sticker[idx][x][y] == 0)continue;
                    if (i + x >= N || j + y >= M) { // 범위를 벗어나면 실패
                        flag = false;
                        break;
                    }
                    if (notebook[i + x][j + y]) { //이미 스티커가 붙어있으면 실패
                        flag = false;
                        break;
                    }
                }
            }
            if (flag) { // 스티커를 붙일 수 있으면
                for (int x = 0; x < R[idx]; x++) {
                    for (int y = 0; y < C[idx]; y++) {
                        if (sticker[idx][x][y] == 0)continue;
                        notebook[i + x][j + y] = true;
                    }
                }
                return true;
            }
 
        }
 
    }
    return false;
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    cin >> N >> M >> K;
 
    for (int i = 0; i < K; i++) {
        cin >> R[i] >>C[i];
        for (int x = 0; x < R[i]; x++) {
            for (int y = 0; y < C[i]; y++) {
                cin >> sticker[i][x][y];
            }
        }
    }
    
    for (int i = 0; i < K; i++) {
        for (int rotate_cnt = 0; rotate_cnt < 4; rotate_cnt++) {
            if(solve(i)) break;
            rotate(i);
        }
    }
    int cnt = 0;
    for (int i = 0; i < N; i++) {
        for (int j =0; j < M; j++) {
            if (notebook[i][j])cnt++;
        }
    }
    cout << cnt;
 
    return 0;
}
 
 
cs

 

반응형

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

[백준 12094번] 2048 (Hard)  (0) 2022.01.08
[백준 12100번] 2048(Easy)  (0) 2022.01.05
[백준 2636번] 치즈  (0) 2022.01.05
[백준 15683번] 감시  (1) 2022.01.04
[백준 1987번] 알파벳  (0) 2022.01.03

+ Recent posts