반응형

문제 링크

 

14503번: 로봇 청소기

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어

www.acmicpc.net

 

 

풀이 )

  문제에 주어진 조건에 따라 구현하면 된다.

  청소하지 않은 칸은 0, 벽은 1로 입력 받았기 때문에, 청소한 칸은 2를 입력하여 따로 방문 여부를 나타내기위한 배열을 사용하지않았다.

  현재 로봇 청소기의 위치를 청소하고, 왼쪽 방향(d = (d+3)%4) 다음칸(board[nr][nc])을 확인하여 청소하지 않은 칸이면 이동한다.

  주위 4칸이 모두 청소됐거나 벽일 경우 왼쪽으로 4번 회전하여 원래의 방향이므로 현재 방향의 뒷방향으로 이동하기 위해, br = r-dx[d]; bc = c-dy[d];를 취해준 후, 뒤로 이동한다. 이때 뒤가 벽(1)이면 로봇청소기는 멈춘다.

(br, bc)에 대해서는 입력 테두리가 모두 벽으로 둘러쌓였기 때문에 배열 범위 밖으로 나가는 유효성 검사를 해주지 않았다.

 

마지막으로 배열에서 '2'인 칸의 수를 센다.

 

#include <iostream>

using namespace std;

int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};

int board[50][50];

int main(void){
    int n, m;
    cin >> n >> m;

    int r, c, d;
    cin >> r >> c >> d;


    for(int i = 0; i < n; ++i)
        for(int j = 0; j < m; ++j)
            cin >> board[i][j];

    int cnt = 0;
    while(1){
        board[r][c] = 2;
        bool flag = false;
        for(int i = 0; i < 4; ++i){
            d = (d+3)%4;
            int nr = r+dx[d];
            int nc = c+dy[d];
            if(!board[nr][nc]){
                flag = true;
                r = nr;
                c = nc;
                break;
            }
        }
        if(flag)
            continue;

        int br = r-dx[d];
        int bc = c-dy[d];
        if(board[br][bc] == 1)
            break;
        r = br;
        c = bc;
    }

    int ans = 0;
    for(int i = 0; i < n; ++i)
        for(int j = 0; j < m; ++j)
            if(board[i][j] == 2)
                ans++;

    cout << ans << '\n';
}

 

반응형
반응형

문제 링크

 

15684번: 사다리 조작

사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선

www.acmicpc.net

 

 

풀이 )

  사다리에서 'ㅏ' 모양과 'ㅓ'모양을 구분하기 위해 line배열에서 각각 1, 2로 저장했다.

  이후 DFS로 가로선을 추가할 수 있는 곳에 0개부터 3개까지 추가한다.(makeLine( ))

  가로선을 추가할 때, 중복을 제거하기 위해, curH, curN을 넘겨주었다. (중복을 제거하지 않는 경우 시간초과)

  climbing( )에서는 위에서부터 사다리를 타면서 가로선을 만나면 2개씩 교체를 해서 끝까지 내려간 후, 끝까지 도달했을 때 순서가 맞는지 확인한다.

 

#include <iostream>
#include <algorithm>

using namespace std;

int line[31][11];
int n, m, h;

bool climbing(void){
    int arr[11] = {0, };
    for(int i = 1; i <= n; ++i)
        arr[i] = i;

    for(int i = 1; i <= h; ++i){
        for(int j = 1; j <= n-1; ++j){
            if(line[i][j] == 1)
                swap(arr[j], arr[j+1]);
        }
    }

    for(int i = 1; i <= n; ++i){
        if(arr[i] != i)
            return false;
    }
    return true;
}

bool makeLine(int cnt, int dst, int curN, int curH){

    if(cnt == dst)
        return climbing();

    bool ret;
    for(int i = 1; i <= h; ++i){
        if(i < curH)
            continue;
        for(int j = 1; j <= n-1; ++j){
            if(i == curH && j <= curN)
                continue;
            if(line[i][j] || line[i][j+1])
                continue;

            line[i][j] = 1;
            line[i][j+1] = 2;
            if(makeLine(cnt+1, dst, j, i))
                return true;
            line[i][j] = 0;
            line[i][j+1] = 0;
        }
    }
    return false;
}

int main(void){
    cin >> n >> m >> h;
    while(m--){
        int a, b;
        cin >> a >> b;
        line[a][b] = 1;
        line[a][b+1] = 2;
    }

    for(int i = 0; i < 4; ++i){
        if(makeLine(0, i, 0, 0)){
            cout << i << '\n';
            return 0;
        }
    }

    cout << -1 << '\n';
    return 0;
}

 

주의 )

  가로선을 추가하는 과정에서의 중복 제거

  아래는 중복을 제거하지 않아 시간 초과한 코드다.

#include <iostream>
#include <algorithm>

using namespace std;

int line[31][11];
int n, m, h;

bool climbing(void){
    int arr[11] = {0, };
    for(int i = 1; i <= n; ++i)
        arr[i] = i;

    for(int i = 1; i <= h; ++i){
        for(int j = 1; j <= n-1; ++j){
            if(line[i][j] == 1)
                swap(arr[j], arr[j+1]);
        }
    }

    for(int i = 1; i <= n; ++i){
        if(arr[i] != i)
            return false;
    }
    return true;
}

bool makeLine(int cnt, int dst){

    if(cnt == dst)
        return climbing();

    bool ret;
    for(int i = 1; i <= h; ++i){
        for(int j = 1; j <= n-1; ++j){
            if(line[i][j] || line[i][j+1])
                continue;

            line[i][j] = 1;
            line[i][j+1] = 2;
            if(makeLine(cnt+1, dst))
                return true;
            line[i][j] = 0;
            line[i][j+1] = 0;
        }
    }
    return false;
}

int main(void){
    cin >> n >> m >> h;
    while(m--){
        int a, b;
        cin >> a >> b;
        line[a][b] = 1;
        line[a][b+1] = 2;
    }

    for(int i = 0; i < 4; ++i){
        if(makeLine(0, i)){
            cout << i << '\n';
            return 0;
        }
    }

    cout << -1 << '\n';
    return 0;
반응형
반응형

문제 링크

 

5373번: 큐빙

각 테스트 케이스에 대해서 큐브를 모두 돌린 후의 윗 면의 색상을 출력한다. 첫 번째 줄에는 뒷 면과 접하는 칸의 색을 출력하고, 두 번째, 세 번째 줄은 순서대로 출력하면 된다. 흰색은 w, 노란

www.acmicpc.net

 

 

풀이 )

  주사위의 6면을 각각 배열로 나타낸 다음 주어진 순서대로 큐브를 돌린다.

  3차원 배열로 나타내면 헷갈릴까봐 6개의 2차원 배열로 나타냈다.

  

#include <iostream>
#include <string>
#include <vector>

using namespace std;

void rotate(vector<vector<int>>& face, int dir){
    int tmp = face[0][0];
    if(dir == 1){   // 시계
        int tmp2 = face[1][0];
        face[0][0] = face[2][0];
        face[1][0] = face[2][1];
        face[2][0] = face[2][2];
        face[2][1] = face[1][2];
        face[2][2] = face[0][2];
        face[1][2] = face[0][1];
        face[0][2] = tmp;
        face[0][1] = tmp2;
    }
    else{   // 반시계
        int tmp2 = face[0][1];
        face[0][0] = face[0][2];
        face[0][1] = face[1][2];
        face[0][2] = face[2][2];
        face[1][2] = face[2][1];
        face[2][2] = face[2][0];
        face[2][1] = face[1][0];
        face[2][0] = tmp;
        face[1][0] = tmp2;
    }
}

int main(void){
    char color[] = {'w', 'r', 'g', 'b', 'o', 'y'};
    int t;
    cin >> t;
    while(t--){
        vector<vector<int>> u(3, vector<int>(3, 0));
        vector<vector<int>> f(3, vector<int>(3, 1));
        vector<vector<int>> l(3, vector<int>(3, 2));
        vector<vector<int>> r(3, vector<int>(3, 3));
        vector<vector<int>> b(3, vector<int>(3, 4));
        vector<vector<int>> d(3, vector<int>(3, 5));
        int n;
        cin >> n;
        while(n--){
            string str;
            cin >> str;
            if(str == "L-"){
                for(int i = 0; i < 3; ++i){
                    int tmp = f[i][0];
                    f[i][0] = d[i][0];
                    d[i][0] = b[i][0];
                    b[i][0] = u[i][0];
                    u[i][0] = tmp;
                }
                rotate(l, 0);
            }
            else if(str == "L+"){
                for(int i = 0; i < 3; ++i){
                    int tmp = f[i][0];
                    f[i][0] = u[i][0];
                    u[i][0] = b[i][0];
                    b[i][0] = d[i][0];
                    d[i][0] = tmp;
                }
                rotate(l, 1);
            }
            else if(str == "R-"){
                for(int i = 0; i < 3; ++i){
                    int tmp = f[i][2];
                    f[i][2] = u[i][2];
                    u[i][2] = b[i][2];
                    b[i][2] = d[i][2];
                    d[i][2] = tmp;
                }
                rotate(r, 0);
            }
            else if(str == "R+"){
                for(int i = 0; i < 3; ++i){
                    int tmp = f[i][2];
                    f[i][2] = d[i][2];
                    d[i][2] = b[i][2];
                    b[i][2] = u[i][2];
                    u[i][2] = tmp;
                }
                rotate(r, 1);
            }
            else if(str == "F-"){
                for(int i = 0; i < 3; ++i){
                    int tmp = u[2][i];
                    u[2][i] = r[2][i];
                    r[2][i] = d[0][2-i];
                    d[0][2-i] = l[2][i];
                    l[2][i] = tmp;
                }
                rotate(f, 0);
            }
            else if(str == "F+"){
                for(int i = 0; i < 3; ++i){
                    int tmp = u[2][i];
                    u[2][i] = l[2][i];
                    l[2][i] = d[0][2-i];
                    d[0][2-i] = r[2][i];
                    r[2][i] = tmp;
                }
                rotate(f, 1);
            }
            else if(str == "B-"){
                for(int i = 0; i < 3; ++i){
                    int tmp = u[0][i];
                    u[0][i] = l[0][i];
                    l[0][i] = d[2][2-i];
                    d[2][2-i] = r[0][i];
                    r[0][i] = tmp;
                }
                rotate(b, 0);
            }
            else if(str == "B+"){
                for(int i = 0; i < 3; ++i){
                    int tmp = u[0][i];
                    u[0][i] = r[0][i];
                    r[0][i] = d[2][2-i];
                    d[2][2-i] = l[0][i];
                    l[0][i] = tmp;
                }
                rotate(b, 1);
            }
            else if(str == "U-"){
                for(int i = 0; i < 3; ++i){
                    int tmp = f[0][i];
                    f[0][i] = l[i][2];
                    l[i][2] = b[2][2-i];
                    b[2][2-i] = r[2-i][0];
                    r[2-i][0] = tmp;
                }
                rotate(u, 0);
            }
            else if(str == "U+"){
                for(int i = 0; i < 3; ++i){
                    int tmp = f[0][i];
                    f[0][i] = r[2-i][0];
                    r[2-i][0] = b[2][2-i];
                    b[2][2-i] = l[i][2];
                    l[i][2] = tmp;
                }
                rotate(u, 1);
            }
            else if(str == "D-"){
                for(int i = 0; i < 3; ++i){
                    int tmp = f[2][i];
                    f[2][i] = r[2-i][2];
                    r[2-i][2] = b[0][2-i];
                    b[0][2-i] = l[i][0];
                    l[i][0] = tmp;
                }
                rotate(d, 0);
            }
            else{
                for(int i = 0; i < 3; ++i){
                    int tmp = f[2][i];
                    f[2][i] = l[i][0];
                    l[i][0] = b[0][2-i];
                    b[0][2-i] = r[2-i][2];
                    r[2-i][2] = tmp;
                }
                rotate(d, 1);
            }
        }

        for(int i = 0; i < 3; ++i){
            for(int j = 0; j < 3; ++j)
                cout << color[u[i][j]];
            cout << '\n';
        }
    }
}

 

주의 )

  회전할 때 각 면의 좌표를 잘 확인해야한다. 각 면의 기준 좌표에 따라 표현하는 방식이 달라지기 때문에 기준을 명확히 정하고, 빈 종이에 전개도를 그리면 실수가 준다.

반응형

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

[C++] 백준 - 4375 : 1  (0) 2020.12.12
[C++] 백준 - 1748 : 수 이어 쓰기 1  (0) 2020.12.12
[C++] 백준 - 14502 : 연구소  (0) 2020.12.09
[C++] 백준 - 9663 : N-Queen  (0) 2020.12.09
[C++] 백준 - 1065 : 한수  (0) 2020.12.07
반응형

문제 링크

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크

www.acmicpc.net

 

풀이 )

  먼저 완전탐색으로 3개의 벽을 세운다.

  벽을 세운 모든 경우에 대해서 바이러스가 퍼진 지도를 BFS로 구한 뒤 바이러스가 퍼지지 않은 좌표의 수의 최댓값을 구한다.

 

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>

using namespace std;

int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
int n, m, ans;
int map[8][8];
queue<int> q;

int spread(void){
    int ret = 0;
    int tmp[8][8];
    memcpy(tmp, map, sizeof(map));
    queue<int> tmpq(q);

    while(!tmpq.empty()){
        int x = tmpq.front()/10;
        int y = tmpq.front()%10;
        tmpq.pop();
        for(int dir = 0; dir < 4; ++dir){
            int xx = x+dx[dir];
            int yy = y+dy[dir];
            if(xx < 0 || xx >= n || yy < 0 || yy >= m)
                continue;
            if(tmp[xx][yy] > 0)
                continue;
            tmp[xx][yy] = 2;
            tmpq.push(xx*10+yy);
        }
    }

    for(int i = 0; i < n; ++i)
        for(int j = 0; j < m; ++j)
            if(tmp[i][j] == 0)
                ret++;

    return ret;
}

void wall(int x, int y, int cnt){
    if(cnt == 3){
        ans = max(ans, spread());
        return;
    }

    for(int i = 0; i < n; ++i){
        for(int j = 0; j < m; ++j){
            if(map[i][j] == 0){
                map[i][j] = 1;
                wall(i, j, cnt+1);
                map[i][j] = 0;
            }
        }
    }
}

int main(void){
    cin >> n >> m;
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < m; ++j){
            cin >> map[i][j];
            if(map[i][j] == 2)
                q.push(i*10+j);
        }
    }

    wall(0, 0, 0);
    cout << ans << '\n';
}

 

주의 )

  바이러스가 퍼질 때, 지도와 바이러스의 위치를 담은 queue를 각각 복사해서 사용해야 다음번 시도에 영향을 주지 않는다.

반응형

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

[C++] 백준 - 1748 : 수 이어 쓰기 1  (0) 2020.12.12
[C++] 백준 - 5373 : 큐빙  (0) 2020.12.09
[C++] 백준 - 9663 : N-Queen  (0) 2020.12.09
[C++] 백준 - 1065 : 한수  (0) 2020.12.07
[C++] 백준 - 17144 : 미세먼지 안녕!  (0) 2020.12.07
반응형

문제 링크

 

17144번: 미세먼지 안녕!

미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사

www.acmicpc.net

 

풀이 )

  미세먼지 확산 전 격자판을 a 배열에 저장하고, 변화량을 b 배열에 저장했다. (a 배열에 모두 저장하는 경우, 변화가 순차적으로 일어나는게 아니기 때문에 불가능했다.)

  b 배열의 경우 확산이 일어날 수 있는 방향(벽이 아니고, 공기청정기가 아닌 방향)의 개수에 따라 각 방향에 1/5에 해당되는 값을 더해주고, 해당 칸의 값에 1/5를 빼주었다.

  이후 공기청정기의 윗부분 순환과 아랫부분 순환을 구현해준 후, 마지막으로 모든 칸의 미세먼지 양을 더해준다.

  

#include <iostream>
#include <cstring>

using namespace std;

int r, c, t;
int cx1, cx2;
int a[50][50];
int b[50][50];
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};

void diffu(int x, int y){
    for(int i = 0; i < 4; ++i){
        int xx = x+dx[i];
        int yy = y+dy[i];
        if(xx < 0 || xx >= r || yy < 0 || yy >= c)
            continue;
        if((xx == cx1 || xx == cx2) && yy == 0)
            continue;
        b[xx][yy] += a[x][y]/5;
        b[x][y] -= a[x][y]/5;
    }
}

void airCleaner1(int cx){
    for(int i = cx-1; i > 0; --i){
        if(cx == 1)
            break;
        a[i][0] = a[i-1][0];
    }
    for(int i = 0; i < c-1; ++i)
        a[0][i] = a[0][i+1];
    for(int i = 0; i < cx; ++i)
        a[i][c-1] = a[i+1][c-1];
    for(int i = c-1; i > 1; --i)
        a[cx][i] = a[cx][i-1];
    a[cx][1] = 0;
}

void airCleaner2(int cx){
    for(int i = cx+1; i < r-1; ++i){
        if(cx == r-2)
            break;
        a[i][0] = a[i+1][0];
    }
    for(int i = 0; i < c-1; ++i)
        a[r-1][i] = a[r-1][i+1];
    for(int i = r-1; i > cx; --i)
        a[i][c-1] = a[i-1][c-1];
    for(int i = c-1; i > 1; --i)
        a[cx][i] = a[cx][i-1];
    a[cx][1] = 0;
}

int main(void){
    cin >> r >> c >> t;
    for(int i = 0; i < r; ++i)
        for(int j = 0; j < c; ++j){
            cin >> a[i][j];
            if(a[i][j] == -1 && a[i-1][j] == -1){
                cx1 = i-1;
                cx2 = i;
            }
        }

    while(t--){
        memset(b, 0, sizeof(b));
        for(int i = 0; i < r; ++i)
            for(int j = 0; j < c; ++j)
                if(a[i][j])
                    diffu(i, j);
        for(int i = 0; i < r; ++i)
            for(int j = 0; j < c; ++j)
                a[i][j] += b[i][j];
        airCleaner1(cx1);
        airCleaner2(cx2);
    }

    int ans = 0;
    for(int i = 0; i < r; ++i)
        for(int j = 0; j < c; ++j)
            if(a[i][j] != -1)
                ans += a[i][j];

    cout << ans << '\n';
}

 

주의 )

  순환 시 4방향에 따른 반복문 내 반복 횟수

반응형

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

[C++] 백준 - 9663 : N-Queen  (0) 2020.12.09
[C++] 백준 - 1065 : 한수  (0) 2020.12.07
[C++] 백준 - 14499 : 주사위 굴리기  (0) 2020.12.05
[C++] 백준 - 1874 : 스택 수열  (0) 2020.12.01
[C++] 백준 - 10773 : 제로  (0) 2020.12.01
반응형

문제 링크

 

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

 

풀이 )

  문제를 풀기에 앞서 주사위를 어떻게 표현할지를 생각해봐야한다.

  주사위의 삼면을 정하면 나머지 삼면은 고정되기 때문에 윗면, 오른쪽면, 앞면을 각각 diceU, diceR, diceF로 설정했다.

(아랫면, 왼쪽, 뒷면은 각각 5-diceU, 5-diceR, 5-diceF(눈의 수 1~6이 아닌 인덱스 0~5로 이루어져있기 때문에))

  동, 서, 남, 북에 대해서 순서대로 구현을 했다. (이동에 앞서 바깥으로 이동시키는 경우 해당 명령어를 무시한다.)

  • 동쪽 이동: 윗면이 오른쪽면으로 가고, 왼쪽면이 윗면으로 간다.
  • 서쪽 이동: 윗면이 왼쪽면으로 가고, 오른쪽면이 윗면으로 간다.
  • 남쪽 이동: 윗면이 앞면으로 가고, 뒷면이 윗면으로 간다.
  • 북쪽 이동: 윗면이 뒷면으로 가고, 앞면이 윗면으로 간다.

이후 지도를 확인하여

  • 0인 경우 주사위 밑면(dice[5-diceU])의 값을 지도 칸에 저장하고
  • 0이 아닌 경우 지도의 값을 주사위 밑면에 저장하고, 해당 지도 칸의 값을 0으로 만든다.

마지막으로 주사위의 윗면의 수(dice[diceU])를 출력한다.

 

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector<vector<int>> map;
int dice[6] = {0, };
int diceU = 0, diceR = 2, diceF = 4;
int x, y;

void move_print(void){
    if(map[x][y]){
        dice[5-diceU] = map[x][y];
        map[x][y] = 0;
    }
    else
        map[x][y] = dice[5-diceU];
    cout << dice[diceU] << '\n';
}

int main(void){
    int n, m, k;
    cin >> n >> m >> x >> y >> k;
    for(int i = 0; i < n; ++i){
        vector<int> tmp;
        for(int j = 0; j < m; ++j){
            int cell;
            cin >> cell;
            tmp.push_back(cell);
        }
        map.push_back(tmp);
    }

    while(k--){
        int com;
        cin >> com;

        if(com == 1){
            if(y == m-1)
                continue;
            y++;
            swap(diceU, diceR);
            diceU = 5-diceU;
        }
        else if(com == 2){
            if(y == 0)
                continue;
            y--;
            swap(diceU, diceR);
            diceR = 5-diceR;
        }
        else if(com == 3){
            if(x == 0)
                continue;
            x--;
            swap(diceU, diceF);
            diceF = 5-diceF;
        }
        else{
            if(x == n-1)
                continue;
            x++;
            swap(diceU, diceF);
            diceU = 5-diceU;
        }
        move_print();
    }
    return 0;
}

 

주의 )

- 문제에서 주어지는 좌표 x, y의 순서에 유의한다. (세로, 가로)

반응형

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

[C++] 백준 - 1065 : 한수  (0) 2020.12.07
[C++] 백준 - 17144 : 미세먼지 안녕!  (0) 2020.12.07
[C++] 백준 - 1874 : 스택 수열  (0) 2020.12.01
[C++] 백준 - 10773 : 제로  (0) 2020.12.01
[C++] 백준 - 5430 : AC  (0) 2020.11.30

+ Recent posts