본문 바로가기

알고리즘/SW Expert Academy

[모의 SW 역량테스트] 4013. 특이한 자석

반응형

[모의 SW 역량테스트] 특이한 자석


1. 이해하기

  • 4개의 자석이 있고, 각 자석은 8개의 날을 가지고 있다.
  • 자석의 각 날 마다 N극 또는 S극의 자성을 가지고 있다.
  • 하나의 자석이 1 칸 회전될 때, 붙어 있는 자석은 서로 붙어 있는 날의 자성과 다를 경우에만 인력에 의해 반대 방향으로 1칸 회전된다.
  • 모든 회전이 끝난 후, 아래와 같은 방법으로 점수를 계산한다.
    • 1 번 자석에서 빨간색 화살표 위치에 있는 날의 자성이 N 극이면 0점, S 극이면 1점을 획득한다.
    • 2 번 자석에서 빨간색 화살표 위치에 있는 날의 자성이 N 극이면 0점, S 극이면 2점을 획득한다.
    • 3 번 자석에서 빨간색 화살표 위치에 있는 날의 자성이 N 극이면 0점, S 극이면 4점을 획득한다.
    • 4 번 자석에서 빨간색 화살표 위치에 있는 날의 자성이 N 극이면 0점, S 극이면 8점을 획득한다.
  • 자석을 K번 회전시킨 후 점수의 총 합을 구하는 문제.
  • 시뮬레이션 문제.

2. 구현하기

  • 자석을 시계방향, 반 시계방향으로 회전시켰을 때, 자석의 모양을 구현한다.

    void rotate_clockwise(int num) {
        int t = magnetic[num][0];
        for(int i = 8; i > 1; i--) {
            magnetic[num][i%8] = magnetic[num][i-1];
        }
        magnetic[num][1] = t;
    }
    
    void rotate_anticlockwise(int num) {
        int t = magnetic[num][0];
        for(int i = 0; i < 7; i++) {
            magnetic[num][i] = magnetic[num][i+1];
        }
        magnetic[num][7] = t;
    }
  • 현재 주어진 번호의 왼쪽, 오른쪽으로 가면서 자석이 붙어있는 날이 다른 극을 가지고 있는지 확인한다. 이 때, 다르다면 탐색을 멈춘다.

    void get_left_diff(vector<INF>& inf, int num, int dir) {
        int n_dir = -dir;
        for(int i = num; i-1 >= 0; i--) {
            if(magnetic[i-1][2] == magnetic[i][6]) break;
            inf.push_back({i-1,n_dir});
            n_dir = -n_dir;
        }
    }
    
    void get_right_diff(vector<INF>& inf, int num, int dir) {
        int n_dir = -dir;
        for(int i = num; i+1 < 4; i++) {
            if(magnetic[i+1][6] == magnetic[i][2]) break;
            inf.push_back({i+1,n_dir});
            n_dir = -n_dir;
        }
    }
  • 어느 번호의 자석을 돌려야 할 지 구한 것을 바탕으로 회전을 시킨다.

    void rotate(vector<INF>& inf) {
        int size = inf.size();
        for(int i = 0; i < size; i++) {
            INF now = inf[i];
            if(now.dir == 1) rotate_clockwise(now.num);
            else rotate_anticlockwise(now.num);
        }
    }
    
    void simulate() {
        for(int k = 0; k < K; k++) {
            int num,dir;
            cin >> num >> dir;
            num--;
            vector<INF> inf;
            inf.push_back({num,dir});
            get_left_diff(inf,num,dir);
            get_right_diff(inf,num,dir);
            rotate(inf);
        }
    }
  • K번 회전시킨 후, 점수를 구한다.

    int get_score() {
        int ret = 0;
        for(int i = 0; i < 4; i++) {
            ret += magnetic[i][0]*(1<<i);
        }
        return ret;
    }

3. 전체 코드

#include <iostream>
#include <vector>
using namespace std;
struct INF{
    int num,dir;
};
int magnetic[4][8];
int K;

void rotate_clockwise(int num) {
    int t = magnetic[num][0];
    for(int i = 8; i > 1; i--) {
        magnetic[num][i%8] = magnetic[num][i-1];
    }
    magnetic[num][1] = t;
}

void rotate_anticlockwise(int num) {
    int t = magnetic[num][0];
    for(int i = 0; i < 7; i++) {
        magnetic[num][i] = magnetic[num][i+1];
    }
    magnetic[num][7] = t;
}

int get_score() {
    int ret = 0;
    for(int i = 0; i < 4; i++) {
        ret += magnetic[i][0]*(1<<i);
    }
    return ret;
}

void rotate(vector<INF>& inf) {
    int size = inf.size();
    for(int i = 0; i < size; i++) {
        INF now = inf[i];
        if(now.dir == 1) rotate_clockwise(now.num);
        else rotate_anticlockwise(now.num);
    }
}

void get_left_diff(vector<INF>& inf, int num, int dir) {
    int n_dir = -dir;
    for(int i = num; i-1 >= 0; i--) {
        if(magnetic[i-1][2] == magnetic[i][6]) break;
        inf.push_back({i-1,n_dir});
        n_dir = -n_dir;
    }
}

void get_right_diff(vector<INF>& inf, int num, int dir) {
    int n_dir = -dir;
    for(int i = num; i+1 < 4; i++) {
        if(magnetic[i+1][6] == magnetic[i][2]) break;
        inf.push_back({i+1,n_dir});
        n_dir = -n_dir;
    }
}

void simulate() {
    for(int k = 0; k < K; k++) {
        int num,dir;
        cin >> num >> dir;
        num--;
        vector<INF> inf;
        inf.push_back({num,dir});
        get_left_diff(inf,num,dir);
        get_right_diff(inf,num,dir);
        rotate(inf);
    }
}

void input() {
    cin >> K;
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 8; j++) {
            cin >> magnetic[i][j];
        }
    }
}

int main() {
    int T;
    cin >> T;
    for(int t = 1; t <= T; t++) {
        input();
        simulate();
        cout << '#' << t << ' ' << get_score() << '\n';
    }
    return 0;
}