컴퓨터기본/문제풀이

[SWEA] 4013. 특이한 자석

차가운오미자 2021. 10. 9. 12:11

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWIeV9sKkcoDFAVH 

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

문제 이해

거의 그냥 시뮬레이션 문제인데, 내가 문제를 또 잘못봐서 한참을 헤맸다.

최종 점수를 판단하는 건 모든 cmd를 수행하고 난 후이다! 난 cmd를 한 번 실행할 때마다 점수가 나는 건줄 알았다...

 

cmd를 하나씩 수행할 때, 

- 좌우에 다른 극인 자석이 있으면 걔네를 돌린다. 

- visited 배열을 하나 두어서 이미 한번 돌렸던 애가 다시 돌아가지 않게 한다.

  • 예를 들어 2번 자석이 돌아감 > 3번 자석 다른 극이라 돌아감 > 3번의 좌측인 2번 자석은 이미 움직였으므로 돌리지 않고, 우측인 4번 자석이 다른 극이면 움직인다.
  • 당연히 이 visited 배열은 cmd하나 끝나면 초기화가 필요하다

자석이 도는 동작 자체는 배열을 한 칸씩 왼쪽 혹은 오른쪽으로 옮겨주면 된다.

이게 헷갈릴 수 있으니 단순 배열을 가지고 실험을 해보자.

 

작성 코드 (C)

#include <stdio.h>
 
int K;
int magnet[4+2][8+2];
 
int cmd[20][2]; //0: 자석 넘버, 1: 방향
int visited[4];
 
void getInput(void){
 
    scanf("%d", &K);
    for(int i = 0; i<4; i++){
        for(int j = 0; j<8; j++){
            scanf("%d", &magnet[i][j]);
        }
    }
    for(int i = 0; i<K; i++){
        scanf("%d %d", &cmd[i][0], &cmd[i][1]);
        cmd[i][0]--;
    }
}
 
void turn(int idx, int dir){
     
    visited[idx] = 1;
    // 옆에 자석 살피기
    // 본인이 움직일 수 있는지 파악
    if(idx-1 >= 0){
        // 좌측에 자석 있음
        if(magnet[idx][6] != magnet[idx-1][2]){
            // 다른 극임 -> 돌아감
            if(visited[idx-1] != 1) turn(idx-1, (-1)*dir);
        }
    }
    if(idx+1 < 4){
        // 우측에 자석 있음
        if(magnet[idx][2] != magnet[idx+1][6]){
            // 다른 극임 -> 돌아감
            if(visited[idx+1] != 1) turn(idx+1, -dir);
        }
    }
     
    // 자석 돌리기
    if(dir == 1){ // 시계 방향일 경우
        int tmp = magnet[idx][7];
        for(int i = 7; i>=1; i--){
            magnet[idx][i] = magnet[idx][i-1];
        }
        magnet[idx][0] = tmp;
    }
    if (dir == -1){ // 반시계 방향일 경우
        int tmp = magnet[idx][0];
        for(int i = 1; i<8; i++){
            magnet[idx][i-1] = magnet[idx][i];
        }
        magnet[idx][7] = tmp;
    }
    //printf("turned magnet %d in %d direction\n", idx, dir);
}
 
int countPnt(void){
    // 현재 자석 상태에서 포인트가 어떻게 나는지
    int pnt = 0;
    for(int i = 0; i<4; i++){
        if(magnet[i][0] == 0) continue; // N극임, 점수 없음
        else{
            // S극임, 2^i 만큼의 점수를 얻는다.
            pnt += (1 << i);
        }
    }
    return pnt;
}
 
int Solve(void){
    int pnt = 0;
    for(int i = 0; i<K; i++){
        // K번 만큼 돌림
        turn(cmd[i][0], cmd[i][1]);
        //printf("-----cmd %d done----\n", i);
        for(int j = 0; j<4; j++) visited[j] = 0; // 초기화
    }
    // 회전 다 함
    pnt = countPnt();
    return pnt;
}
 
int main(void){
 
    int T, ans;
    scanf("%d", &T);
    for(int i = 0; i<T; i++){
        getInput();
        ans = Solve();
        printf("#%d %d\n", i+1, ans);
    }
    return 0;
}

'컴퓨터기본 > 문제풀이' 카테고리의 다른 글

[SWEA] 5644. 무선 충전  (0) 2021.10.09
[SWEA] 4014. 활주로 건설  (0) 2021.10.09
[정올] 2893 : 제리의 치즈먹기 (Cheese)  (0) 2021.10.09
[SWEA] 2383. 점심 식사시간  (0) 2021.10.09
[백준] 2477번: 참외밭  (2) 2021.09.26