반응형

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

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

1. 문제설명

구현함에 있어서 문제의 단계를 꼼꼼히 보아야하는 문제

각 파이어볼이 모두 이동한 후에 합쳐져야 하므로

현재 배열에 존재하는 파이어볼을 기준으로

새로운 배열에 파이어볼의 이동을 담아야한다.

 

 

 

2.문제풀이코드 C++

#include <bits/stdc++.h>

using namespace std;
int N, M, K;

struct fireBall {
    int m, s, d;
};

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

vector<fireBall> arr[51][51];
void Input();

void move() {
    vector<fireBall> nextState[51][51];
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            if (arr[i][j].size() > 0) {
                for (auto k: arr[i][j]) {
                    int nx = (i + dx[k.d] * k.s) % N;
                    int ny = (j + dy[k.d] * k.s) % N;
                    if (nx <= 0) nx += N;
                    if (ny <= 0) ny += N;
                    nextState[nx][ny].push_back({k.m, k.s, k.d});
                }
            }
        }
    }

    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            if (nextState[i][j].size() > 1) {
                int sumM = 0;
                int sumS = 0;
                bool dirSame = true;
                int dir = nextState[i][j][0].d % 2;
                for (auto k: nextState[i][j]) {
                    if (k.d % 2 != dir) {
                        dirSame = false;
                    }
                    sumS += k.s;
                    sumM += k.m;
                }

                int newM = sumM / 5;
                int newS = sumS / nextState[i][j].size();

                //new fireball 4
                nextState[i][j].clear();
                if (newM <= 0) continue;

                int newDir = 0;
                if (!dirSame) newDir = 1;

                for (int k = 0; k < 4; k++) {
                    nextState[i][j].push_back({newM, newS, newDir});
                    newDir += 2;
                }
            }
        }
    }
    swap(nextState, arr);
}


int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    Input();
    for (int i = 0; i < K; i++) {
        move();
    }

    int ans = 0;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            for (auto k: arr[i][j]) {
                ans += k.m;
            }
        }
    }
    cout << ans << '\n';
}

void Input() {
    cin >> N >> M >> K;
    for (int i = 0; i < M; i++) {
        int r, c, m, d, s;
        cin >> r >> c >> m >> s >> d;
        arr[r][c].push_back({m, s, d});
    }
}

 

반응형
반응형

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

 

20055번: 컨베이어 벨트 위의 로봇

길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부

www.acmicpc.net

1. 문제설명

벨트가 회전함에 따라

각 벨트 번호의 내구도가 한칸씩 옮겨지고 로봇또한 한칸씩 옮겨지는 것을 구현하고,

벨트위에 있는 로봇을 옮길 수 있는지 확인한 후 한 칸씩 옮기는 것을 구현해야하는 문제이다.

 

이를 구현하기 위해

벨트의 번호에 따른 내구도를 나타내는 배열을 만들고

벨트의 번호에 따라 로봇이 있는지 여부를 나타내는 배열을 만들어서

회전시키는 것을 구현하면 된다.

 

단순 회전은 큐를 이용하면 쉽겠지만

이 문제에서는 각 로봇에 대해 접근을 해야하기 때문에

차라리 배열을 이용하는 것이 괜찮은 것 같다.

큐를 이용하면 회전을 빠르게 구현 할 수 있겠지만

결국 각 벨트 번호에 대한 로봇의 여부를 구하기 위해 인덱스접근하는데 O(n)이 필요하기 떄문이다.

 

 

2.문제풀이코드 C++

#include <bits/stdc++.h>

using namespace std;
int N, K;
void Input();

int durability[202];
bool robots[101];


void beltRotate(){
    int beltLast = durability[2*N];
    for(int i=2*N; i>1; i--){
        durability[i] = durability[i-1];
    }
    durability[1] = beltLast;

    for(int i=N; i>=1; i--){
        robots[i] = robots[i-1];
    }
    robots[N] = 0;


    for(int i=N-1; i>=1; i--){
        if(robots[i]){
            if(durability[i+1] > 0 && !robots[i+1]){
                durability[i+1]--;
                robots[i+1] = 1;
                robots[i] = 0;

                if(i+1 ==N) robots[i+1] =0;
            }
        }
    }

    if(durability[1] > 0){
        robots[1] = 1;
        durability[1]--;
    }
}

bool check(){
    int cnt = 0;
    for(int i=1; i<=2*N; i++){
        if(durability[i]==0){
            cnt++;
        }
    }

    return cnt >= K;
}


int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    Input();

    int turn = 1;
    while(1){
        beltRotate();
        if(check()){
            cout << turn << '\n';
            return 0;
        }
        turn++;
    }
}



void Input() {
    cin >> N >> K;
    for(int i=1; i<=2*N; i++){
        cin >> durability[i];
    }
}
반응형
반응형

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

 

19238번: 스타트 택시

첫 줄에 N, M, 그리고 초기 연료의 양이 주어진다. (2 ≤ N ≤ 20, 1 ≤ M ≤ N2, 1 ≤ 초기 연료 ≤ 500,000) 연료는 무한히 많이 담을 수 있기 때문에, 초기 연료의 양을 넘어서 충전될 수도 있다. 다

www.acmicpc.net

1.문제설명

택시가 손님을 정해진 위치에 데려다 주면서 이동한 거리를 바탕으로 연료의 양을 조건에 따라 계산해야하는 문제이다.

 

이 문제를 풀기 위해 BFS가 여러번 쓰인다.

 

 

1. 첫번째로 택시가 모든 손님과 모든 손님의 도착점으로 이동할 수 있는지 검사해야한다.

벽으로 경로가 끊어져 있을 수 있기 때문에 Flood Fill 방식으로 계산한다.

 

2. 두번째로 가까이 있는 손님을 구하기 위해 Flood Fill 방식으로 다시

현재 택시의 위치와 손님과의 거리를 구한다.

이때 주의해야할 점은 손님을 발견하자마자 BFS를 종료하면 안되고,

손님을 발견하더라도 전체 맵을 다 돌 때까지 BFS를 실행해야한다.

 

map의 크기가 작기 때문에 시간초과에 걸리지 않는다.

이렇게 해야하는 이유는 먼저 모든 손님에 대하여 각 손님까지의 거리를 구한 후

거리가 동일한 경우 행과 열의 숫자를 보고 손님을 정해야하기 때문이다.

만약 BFS를 돌다 손님 하나를 발견하자마자 종료한다면

같은 거리에 위치했지만 행과 열 정보에서 우선순위를 지니는 손님을 탐색하지 못한다.

 

 

3. 세번째는 손님 ---- 도착점 사이의 거리를 구하기 위해 BFS를 사용한다.

Map의 중간 중간 벽이 존재하기 때문에 BFS나 DFS로 거리를 구해야 한다.

 

이러한 세가지 기능을 구현해주면 문제를 해결할 수 있다.

 


2.문제풀이코드 C++

#include <bits/stdc++.h>

using namespace std;
int N, M, F; //F : 초기연료
bool arr[21][21]; //벽
int stx, sty; //driver 시작점
int guestInfo[403][4]; // guest마다 시작x,y 종점x,y
bool checkGuestEnd[403];

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

void Input();

bool gameCheck(int _stx, int _sty) { //flood Fill -> driver로부터 guest 시작점,종점 경로가 연결 되어 있는지확인
    bool ch[21][21] = {0};
    queue<pair<int, int> > Q;

    ch[_stx][_sty] = 1;
    Q.push({_stx, _sty});

    while (!Q.empty()) {
        auto cur = Q.front();
        Q.pop();

        for (int i = 0; i < 4; i++) {
            int nx = cur.first + dx[i];
            int ny = cur.second + dy[i];

            if (nx <= 0 || nx > N || ny <= 0 || ny > N) continue;
            if (ch[nx][ny] || arr[nx][ny]) continue;
            Q.push({nx, ny});
            ch[nx][ny] = 1;
        }
    }

    for (int i = 1; i <= M; i++) {
        int x = guestInfo[i][0];
        int y = guestInfo[i][1];
        int nx = guestInfo[i][2];
        int ny = guestInfo[i][3];

        if (ch[x][y] == 0 || ch[nx][ny] == 0) {
            return false;
        }
    }
    return true;
}

pair<int,int> chooseGuest(int _stx, int _sty){
    int ch[21][21] = {0};
    queue<pair<int, int> > Q;

    ch[_stx][_sty] = 1;
    Q.push({_stx, _sty});

    while (!Q.empty()) {
        auto cur = Q.front();
        Q.pop();

        for (int i = 0; i < 4; i++) {
            int nx = cur.first + dx[i];
            int ny = cur.second + dy[i];

            if (nx <= 0 || nx > N || ny <= 0 || ny > N) continue;
            if (ch[nx][ny] > 0 || arr[nx][ny]) continue;
            Q.push({nx, ny});
            ch[nx][ny] = ch[cur.first][cur.second] + 1;

        }
    }

    int minDist = 100000;
    int nextGuest = -1;

    for(int i=1; i<=M; i++){
        if(checkGuestEnd[i]) continue;

        int curDist = ch[guestInfo[i][0]][guestInfo[i][1]];
        if( curDist< minDist){
            nextGuest = i;
            minDist = curDist;
        }
        else if(curDist == minDist){
            if(guestInfo[nextGuest][0] > guestInfo[i][0]){
                nextGuest = i;
            }
            else if(guestInfo[nextGuest][0] == guestInfo[i][0]){
                if(guestInfo[nextGuest][1] > guestInfo[i][1]){
                    nextGuest = i;
                }
            }
        }
    }

    return {nextGuest, minDist-1};
}

int calDistance(int _stx, int _sty, int enx, int eny){
    int ch[21][21] = {0};
    queue<pair<int, int> > Q;

    ch[_stx][_sty] = 1;
    Q.push({_stx, _sty});

    while (!Q.empty()) {
        auto cur = Q.front();
        Q.pop();

        for (int i = 0; i < 4; i++) {
            int nx = cur.first + dx[i];
            int ny = cur.second + dy[i];

            if (nx <= 0 || nx > N || ny <= 0 || ny > N) continue;
            if (ch[nx][ny] > 0 || arr[nx][ny]) continue;
            Q.push({nx, ny});
            ch[nx][ny] = ch[cur.first][cur.second] + 1;
            if(nx==enx && ny==eny) break;
        }
    }

    return ch[enx][eny]- 1;
}

bool allGuestGoHome(){
    for(int i=1; i<=M; i++){
        if(!checkGuestEnd[i]) return false;
    }
    return true;
}


int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    Input();


    //벽 때문에 깃발이나 손님한테 갈 수 없는 경우
    if (!gameCheck(stx,sty)) {
        cout << -1 << '\n';
        return 0;
    }


    while(!allGuestGoHome()) {
        auto nextGuest = chooseGuest(stx, sty);
        int guest = nextGuest.first;
        int toGuestDist = nextGuest.second;
        int toFlagDist = calDistance(guestInfo[guest][0], guestInfo[guest][1], guestInfo[guest][2], guestInfo[guest][3]);


        if(F<toGuestDist + toFlagDist){
            cout << -1 << '\n';
            return 0;
        }
        else{
            //guest 집에감, 연료 동기화
            checkGuestEnd[guest] = 1;
            F = F - toGuestDist + toFlagDist;

            //driver 이동
            stx = guestInfo[guest][2];
            sty = guestInfo[guest][3];
        }
    }

    cout << F << '\n';
}


void Input() {
    cin >> N >> M >> F;

    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            cin >> arr[i][j];
        }
    }
    //driver start
    cin >> stx >> sty;

    for (int i = 1; i <= M; i++) {
        cin >> guestInfo[i][0] >> guestInfo[i][1] >> guestInfo[i][2] >> guestInfo[i][3]; //start x,y / end x, y
    }


}
반응형
반응형

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

 

19237번: 어른 상어

첫 줄에는 N, M, k가 주어진다. (2 ≤ N ≤ 20, 2 ≤ M ≤ N2, 1 ≤ k ≤ 1,000) 그 다음 줄부터 N개의 줄에 걸쳐 격자의 모습이 주어진다. 0은 빈칸이고, 0이 아닌 수 x는 x번 상어가 들어있는 칸을 의미

www.acmicpc.net

1.문제설명

구현해야할 부분 단위가 많은 시뮬레이션 문제이다.

 

각 부분에 대하여 기능을 잘 분리하고

올바른 순서로 기능을 수행해야 문제를 해결 할 수 있다.

 

주의해야할 점은

모든 상어가 동시에 움직이고 동시에 냄새를 뿌린다는 점이다.

 

즉 상어가 움직이면서 냄새를 뿌리도록 구현하면

잘못된 구현이다.

 

 

 

크게 구현해야할 것은

1. 턴 마다 상어 움직이기

2. 냄새 뿌리기

3. 1번 상어만 남아있는지 확인하기

 

1번을 구현하기 위해서 부분 문제로

각 상어마다 방향정보를 바탕으로

이동해야할 위치와 방향을 구해야한다.

 

이 때 모든 상어는 동시에 움직인다는 조건을 지니므로

상어의 위치를 각 상어마다 옮기고 바로 적용해주는 것이 아니라

현재 위치와 다음 턴의 위치를 구분 짓기 위해서

다른 배열을 하나 두어서 체크를 해주는 것도 중요한 포인트다.

 

 


 

2.문제풀이코드 C++

#include <bits/stdc++.h>
using namespace std;

int N, M, K;
int sharkState[500][3];
int dirPriority[500][5][5];
//20X20 (smell, shark)
int smell[30][30][2];

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


void Input();


void sharkNextState(int sharkNum, int &x, int &y, int &d) {
    int curX = x;
    int curY = y;
    int curD = d;

    //먼저 현재 방향으로 이동 가능한지 체크
    int nx = -1;
    int ny = -1;
    int nd = -1;

    for (int i = 1; i <= 4; i++) {
        nd = dirPriority[sharkNum][curD][i];
        nx = curX + dx[nd];
        ny = curY + dy[nd];

        if (nx <= 0 || nx > N || ny <= 0 || ny > N) continue;
        if (smell[nx][ny][0] > 0) continue;
        x = nx;
        y = ny;
        d = nd;
        return ;
    }

    //네 방향모두 냄새로 가득 차있으니 자신의 냄새있는 칸 찾기
    for (int i = 1; i <= 4; i++) {
        nd = dirPriority[sharkNum][curD][i];
        nx = curX + dx[nd];
        ny = curY + dy[nd];

        if (nx <= 0 || nx > N || ny <= 0 || ny > N) continue;
        if (smell[nx][ny][1] != sharkNum) continue;
        x = nx;
        y = ny;
        d = nd;
        return;
    }
}


void allSharkCheck() {
    bool nextMap[30][30] = {0};
    for (int i = 1; i <= M; i++) {
        int curX = sharkState[i][0];
        int curY = sharkState[i][1];
        int curD = sharkState[i][2];

        //죽은 상어 제외
        if (curX < 0) continue;
        sharkNextState(i, curX, curY, curD);

        //번호 작은 상어 이미 존재
        if (nextMap[curX][curY]) {
            sharkState[i][0] = -1;
            continue;
        }

        sharkState[i][0] = curX;
        sharkState[i][1] = curY;
        sharkState[i][2] = curD;
        nextMap[curX][curY] = 1;
    }
}


bool gameEndCheck() {
    //1번 상어 살아 있고
    if (sharkState[1][0] < 0) return false;
    //다른 상어 모두 죽었을 때
    for (int i = 2; i <= M; i++) {
        if (sharkState[i][0] > 0) {
            return false;
        }
    }
    return true;
}

void spreadSmell(){
    for (int i = 1; i <= M; i++) {
        int curX = sharkState[i][0];
        int curY = sharkState[i][1];
        if (curX < 0) continue;
        smell[curX][curY][0] = K;
        smell[curX][curY][1] = i;
    }
}


void decrementSmell(){
    for(int i=1; i<=N;i++){
        for(int j=1; j<=N; j++){
            if(smell[i][j][0]>0){
                smell[i][j][0]--;
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    Input();
    for (int i = 1; i <= 1000; i++) {
        spreadSmell();
        allSharkCheck();
        if (gameEndCheck()) {
            cout << i << '\n';
            return 0;
        }
        decrementSmell();
    }
    cout << -1 << '\n';
}


void Input() {
    cin >> N >> M >> K;
    //x, y
    for (int x = 1; x <= N; x++) {
        for (int y = 1; y <= N; y++) {
            int sk;
            cin >> sk;

            if (sk > 0) {
                sharkState[sk][0] = x;
                sharkState[sk][1] = y;
            }
        }
    }
    //dir
    for (int i = 1; i <= M; i++) {
        cin >> sharkState[i][2];
    }

    for (int i = 1; i <= M; i++) {
        for (int j = 1; j <= 4; j++) {
            for (int k = 1; k <= 4; k++) {
                cin >> dirPriority[i][j][k];
            }
        }
    }
}
반응형
반응형

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

 

19236번: 청소년 상어

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

www.acmicpc.net

#include <bits/stdc++.h>

using namespace std;


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

int ans = 0;

void moveFish(int _curFishPosition[][4], int _curFishes[][3], int _skx, int _sky) {
    for (int i = 1; i <= 16; i++) {
        int x = _curFishes[i][0];
        int y = _curFishes[i][1];
        int d = _curFishes[i][2];


        if (x < 0) continue;

        int nx = x;
        int ny = y;
        int nd = d;
        for (int j = 0; j < 8; j++) {
            nx = x + dx[nd];
            ny = y + dy[nd];
            nd++;
            if (nd >= 9) nd = 1;

            if (nx < 0 || nx >= 4 || ny < 0 || ny >= 4) continue;
            if (nx == _skx && ny == _sky) continue;

            break;
        }

        nd--;
        if (nd == 0) nd = 8;


        _curFishes[i][0] = nx;
        _curFishes[i][1] = ny;
        _curFishes[i][2] = nd;


        if(_curFishPosition[nx][ny]<=0){
            cout << "Erorr!!" << '\n';
            cout <<_curFishPosition[nx][ny] << ' ' << nx << ' ' << ny << '\n';
        }

        int changeFish = _curFishPosition[nx][ny];
        //살은 경우만 x,y 동기화해줌
        if(_curFishes[changeFish][0] >= 0) {
            _curFishes[changeFish][0] = x;
            _curFishes[changeFish][1] = y;
        }

        swap(_curFishPosition[nx][ny], _curFishPosition[x][y]);

    }
}


void backTrack(int L, int _skx, int _sky, int _skd, int _fishPosition[][4], int _fishes[][3], int sum) {
    ans = max(ans, sum);
    int curFishes[17][3];
    int curFishPosition[4][4];
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            curFishPosition[i][j] = _fishPosition[i][j];
        }
    }
    for (int i = 0; i < 17; i++) {
        for (int j = 0; j < 3; j++) {
            curFishes[i][j] = _fishes[i][j];
        }
    }

    //물고기 이동
    moveFish(curFishPosition, curFishes, _skx, _sky);



    //상어 이동
    int n_skx = _skx;
    int n_sky = _sky;
    int n_skd = _skd;

    for (int i = 0; i < 4; i++) {
        n_skx += dx[_skd];
        n_sky += dy[_skd];


        if (n_skx < 0 || n_skx >= 4 || n_sky < 0 || n_sky >= 4) continue;
        int curFish = curFishPosition[n_skx][n_sky];
        int curFishX = curFishes[curFish][0];

        //물고기 없는 칸 인경우 x==-1
        if (curFishX < 0) continue;
        n_skd = curFishes[curFish][2];

        curFishes[curFish][0] = -1;
        backTrack(L + 1, n_skx, n_sky, n_skd, curFishPosition, curFishes, sum + curFish);
        curFishes[curFish][0] = curFishX;
    }
}


int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int fishPosition[4][4];

//16fishes x, y, dir;
    int fishes[17][3];


    for (int x = 0; x < 4; x++) {
        for (int y = 0; y < 4; y++) {
            int a, b;
            cin >> a >> b;

            fishPosition[x][y] = a;
            fishes[a][0] = x;
            fishes[a][1] = y;
            fishes[a][2] = b;
        }
    }

    int skx = 0;
    int sky = 0;

    //잡아먹으면 0으로 표시
    ans += fishPosition[skx][sky];
    int skd = fishes[fishPosition[skx][sky]][2];
    fishes[fishPosition[skx][sky]][0] = -1;
    backTrack(0, skx, sky, skd, fishPosition, fishes, ans);

    cout << ans << '\n';
}
반응형
반응형

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

 

20061번: 모노미노도미노 2

모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,

www.acmicpc.net

1. 문제설명

구조 설계를 꼼꼼히 잘 해야 해결할 수 있는 문제이다.

먼저 파란색 블록과 초록색 블록 영역은 동일하게 둘 수 있다.

들어오는 블록이 1x2거나 2x1일 때 그 블록을 서로 바꿔서 파란 영역과 초록 영역에 넣어주면 동일한 구조를 지닌다.

 

즉 input 블록만 회전시켜주면 초록색 영역과 파란색 영역에 동일한 시행을 하면 된다.

이를 바탕으로

나는 함수를 세가지를 만들었는데

 

1. 블록을 쌓는 함수,

2. 현재 쌓인 블록에서 지워질 라인이 있는지 확인하고 지우며 점수를 증가시키는 함수

3. 특별한 영역에 블록이 있는지 확인하고 그에 따라 전체 블록을 옮기는 함수.

 

이 세 함수를 들어오는 블록마다 파란영역과 초록 영역에 시행하면

문제를 해결할 수 있다.

 

주의해야할 점은

2. 현재 쌓인 블록에서 지워질 라인이 있는지 확인하고 지운 후

다시 현재 라인부터 검사해야한다.

왜냐하면 현재 라인은 이후에 검사할 라인에서 당겨왔기 때문에

검사가 안된 상태이기 때문이다.

 

 

이러한 삼성기출문제의 구현, 시뮬레이션 문제는 

생각을 구조화하고 짜임새있게 해주어서 좋은 문제인 것 같다.

 

 

2.문제풀이코드 C++

#include <bits/stdc++.h>

using namespace std;

int N, point;
bool blueBoard[4][6], greenBoard[4][6];


void buildBlock(int t, int x, int y, bool board[][6]) {
    if(t==1){
        int ny = 0;
        while(ny+1 <= 5 && board[x][ny+1] ==0 ){
            ny++;
        }
        board[x][ny] = 1;
    }
    else if(t==2){
        int ny = 0;
        while(ny+1 <= 5 && board[x][ny+1] ==0 ){
            ny++;
        }
        board[x][ny] = 1;
        board[x][ny-1] = 1;

    }
    else if(t==3){
        int nyFirst = 0;
        while(nyFirst+1 <= 5 && board[x][nyFirst+1] ==0 ){
            nyFirst++;
        }

        int nySecond = 0;
        while(nySecond+1 <= 5 && board[x+1][nySecond+1] ==0 ){
            nySecond++;
        }

        int ny = min(nyFirst, nySecond);

        board[x][ny] = 1;
        board[x+1][ny] = 1;
    }
}

void checkNormalLine(bool blueBoard[][6]) {
    for(int i=5; i>=2; i--){
        bool flag = true;

        for(int j=0; j<4; j++){
            if(!blueBoard[j][i]){
                flag = false;
                break;
            }
        }

        if(flag){
            //Line delete;
            point++;
            for(int j=i; j>=1; j--){
                for(int k=0; k<4; k++){
                    blueBoard[k][j] = blueBoard[k][j-1];
                }
            }

            for(int k=0; k<4; k++){
                blueBoard[k][0] = 0;
            }
            //cur Line recheck!
            i++;
        }
    }
}

void checkSpecialLine(bool blueBoard[][6]) {
    bool flag0 = false;
    bool flag1 = false;
    for(int i=0; i<4; i++){
        if(blueBoard[i][0]){
            flag0 = true;
        }
        if(blueBoard[i][1]){
            flag1 = true;
        }
    }


    if(flag0&&flag1){
        //2칸
        for(int i=5; i>=2; i--){
            for(int j=0; j<4; j++){
                blueBoard[j][i] = blueBoard[j][i-2];
            }
        }
        for(int k=0; k<4; k++){
            blueBoard[k][0] = 0;
            blueBoard[k][1] = 0;
        }


    }
    else if(flag1){ //1칸
        for(int i=5; i>=1; i--){
            for(int j=0; j<4; j++){
                blueBoard[j][i] = blueBoard[j][i-1];
            }
        }
        for(int k=0; k<4; k++){
            blueBoard[k][0] = 0;
        }

    }

}


int getBlockNum() {
    int blocks = 0;

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 6; j++) {
            if (blueBoard[i][j]) blocks++;
            if (greenBoard[i][j]) blocks++;
        }
    }



    return blocks;
}


void print(){
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 6; j++) {
            cout << blueBoard[i][j] << ' ';
        }
        cout << '\n';
    }

    cout << "-----------------------\n";

    for(int i=0; i<6; i++){
        for(int j=0; j<4; j++){
            cout << greenBoard[j][i] << ' ';
        }
        cout << '\n';
    }


    cout <<'\n';
    cout << "-----------------------\n";
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> N;

    for (int i = 0; i < N; i++) {
        int t, x, y;
        cin >> t >> x >> y;
        buildBlock(t, x, y, blueBoard);
        //90' 회전
        if (t == 2) t = 3;
        else if (t == 3) t = 2;
        buildBlock(t, y, x, greenBoard);

        checkNormalLine(blueBoard);
        checkNormalLine(greenBoard);
        checkSpecialLine(blueBoard);
        checkSpecialLine(greenBoard);
//        print();
    }


    cout << point << '\n';
    cout << getBlockNum() << '\n';

}
반응형
반응형

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

 

17825번: 주사위 윷놀이

첫째 줄에 주사위에서 나올 수 10개가 순서대로 주어진다.

www.acmicpc.net

#include <bits/stdc++.h>

using namespace std;

int dice[11];

int nextPosition[33] ={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,32,22,23,29,25,29,27,28,29,30,31,20,32};
int point[33] = {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,13,16,19,22,24,28,27,26,25,30,35,0};


int horsePosition[4];
int ans = 0;


int horseMove(int x, int cnt){
    //already arrive
    if(x==32) return -1;

    //nx : other horse

    //blue move
    if(x==5){
        x = 21;
        cnt--;
    }
    else if(x==10){
        x = 24;
        cnt--;
    }
    else if(x==15){
        x = 26;
        cnt--;
    }
    //이동
    for(int i=0; i<cnt; i++){
        x = nextPosition[x];
    }

    //other horse
    for(int i=0; i<4; i++){
        if(x!=32 && horsePosition[i] == x){
            return -1;
        }
    }

    return x;
}


void backTrack(int L, int curPoint) {
    if (L == 10) {
        ans = max(ans, curPoint);
        return;
    }

    for (int i = 0; i < 4; i++) {
        int x = horsePosition[i];
        int nx = horseMove(horsePosition[i], dice[L]);
        if (nx < 0) continue;
        horsePosition[i] = nx;
        backTrack(L + 1, point[nx] + curPoint);
        horsePosition[i] = x;
    }
}



int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    for(int i=0; i<10; i++){
        cin >> dice[i];
    }

    backTrack(0, 0);

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

 

반응형
반응형

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

 

17822번: 원판 돌리기

반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀

www.acmicpc.net

1.문제설명

1. 회전하는 함수를 구현한다.

2. 각 원판을 회전 후 인접점을 검사하여 같은 값을 가진 좌표가 있을 경우 해당 지점들은 모두 없앤다.

3. 인접점이 없을 경우 평균을 구해 평균보다 작은 값은 +1 평균보다 큰 값은 모두 -1을 해준다.

 

 

 

1. 회전하는 함수는 deque를 이용하면 쉽게 구현할 수 있다.

2. 인접지점을 검사하는 기능을 구현하는 것이 이 문제의 핵심인데,

규칙을 잘 발견하면 깔끔하게 구할 수 있다.

 

인접지점 중 현재 점과 같은 값을 가진 지점이 존재하는지 검사를 해야하는데

이게 현재 지점이 어떤 점위에 있느냐에 따라 케이스가 나뉘어져

복잡한 if문을 사용해서 풀 수도 있다.

 

그런데 현재 원판이 1번, 2번, ... N번 원판 까지 있으면

가상의 0번 원판, N+1번 원판이 존재한다고 생각하고

해당 원판에 존재하는 수를 모두 0으로 두면

조건을 좀 더 간단하게 만들 수 있다.

 

이런식으로 문제를 풀 수 있는 이유는

문제 조건에서 원판 위의 숫자는 자연수로만 두기 때문에

0과 비교하면 무조건 다른 값을 가진 것으로 나타난다.

 

빨간색 0이 임의로 추가해준 지점이고

파란색 동그라미의 2와 3은 해당 지점에서 인접 지점을 검사할 때

검사할 지점들을 나타낸다

 

이런식으로 구현하면 1번 원판과 N번 원판을 굳이 따로 케이스를 분류하지 않고 풀어도 된다.

 

 


2.문제풀이코드 C++

#include <bits/stdc++.h>

using namespace std;

int N, M, T;
int arr[52][52];

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

void Input();
double getMeans();
void plusMinus();


//row를 k번 돌린다
void rotateClock(int row, int k) {
    deque<int> dq;

    for (int i = 1; i <= M; i++) {
        dq.push_back(arr[row][i]);
    }

    for (int i = 0; i < k; i++) {
        dq.push_front(dq.back());
        dq.pop_back();
    }

    for (int i = 1; i <= M; i++) {
        arr[row][i] = dq.front();
        dq.pop_front();
    }
}

void rotate(int x, int d, int k) {
    for (int i = 1; i <= N; i++) {
        if (i % x == 0) {
            if (d == 0) {
                rotateClock(i, k);
            } else {
                rotateClock(i, M - k);
            }
        }
    }
}

void getAdjacentPoint() {
    vector<pair<int, int> > points;

    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (arr[i][j] == 0) continue;
            for (int k = 0; k < 4; k++) {
                int nx = i + dx[k];
                int ny = j + dy[k];

                if (ny > M) ny = 1;
                else if (ny < 1) ny = M;

                if (arr[i][j] == arr[nx][ny]) {
                    points.push_back({i, j});
                    points.push_back({nx, ny});
                }
            }
        }
    }

    if (points.size() > 0) {
        for (auto p: points) {
            arr[p.first][p.second] = 0;
        }
    } else {
        plusMinus();
    }
}


double getMeans() {
    int cnt = 0;
    double sum = 0;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (arr[i][j] > 0) cnt++;
            sum += arr[i][j];
        }
    }

    if (cnt == 0) return 0;
    else return sum / cnt;
}

void plusMinus() {
    double standard = getMeans();

    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (arr[i][j] == 0) continue;

            if (arr[i][j] > standard) {
                arr[i][j]--;
            } else if (arr[i][j] < standard) {
                arr[i][j]++;
            }
        }
    }
}


int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    Input();

    int ans = 0;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            ans += arr[i][j];
        }
    }

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


void Input() {
    cin >> N >> M >> T;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            cin >> arr[i][j];
        }
    }

    for (int t = 0; t < T; t++) {
        int x, d, k;
        cin >> x >> d >> k;

        rotate(x, d, k);
        getAdjacentPoint();
    }
}
반응형

+ Recent posts