BOJ 1730:: 판화

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

 

말하기조차 부끄러운 실수로 똥을 싸질러 두 번 틀린 결과 끝에 풀었습니다.

반성의 의미로 글을 올립니다.

현재 로봇 팔의 위치를 $(i, j)$, 이 명령을 수행한 후 로봇 팔이 갈 위치를 $(ni, nj)$라고 합시다. 만약 $(ni, nj)$가 목판을 벗어나면 수행할 수 없는 명령이므로 다음 명령으로 건너뜁니다. 수행 가능한 명령이면 $(i, j)$와 $(ni, nj)$가 가로로 인접해있는지 세로로 인접해 있는지에 따라 $(i, j)$와 $(ni, nj)$에 가로줄 또는 세로줄을 추가해줍니다.

예시로

6
URRDLU

를 생각해봅시다.

처음엔 문제에서 제시한대로 $(i, j)$가 $(0, 0)$입니다. 일단 제일 첫 명령 U를 처리합시다. 위로 움직이는 명령이므로 $(ni, nj)$는 $(-1, 0)$인데, 목판을 벗어나므로 명령을 무시하고 다음 명령 R로 넘어갑니다.

여전히 $(i, j)$는 $(0, 0)$이고 이번엔 오른쪽으로 움직이는 명령이므로 $(ni, nj)$는 $(0, 1)$입니다. 따라서 수행 가능한 명령이고, $(i, j)$와 $(ni, nj)$가 가로로 인접해 있으므로 두 칸에 가로줄을 추가합니다. $(i, j)$를 $(0, 1)$로 바꾸고 (로봇 팔 이동) 다음 명령 R로 넘어갑시다.

똑같은 방법으로 가로줄을 추가해줬습니다. $(i, j)$를 $(0, 2)$로 바꾸고 다음 명령 L로 넘어갑시다.

역시 수행 가능한 명령이고, 이번엔 상하로 인접했으므로 두 칸에 세로줄을 추가해줍니다. 이와 같은 방식으로 모든 명령을 처리하면 아래와 같은 판화가 그려집니다.

각 칸마다 가로줄이 추가됐냐 세로줄이 추가됐냐는 불린 배열 2개를 만들어서 저장해도 되는데, 저는 문제 분류대로 비트마스크를 썼습니다. 가로줄은 1, 세로줄은 2로 하고 추가는 or 연산으로 하면 됩니다.

 

#include<cstdio>
#include<cstring>
 
 
using namespace std;
 
 
int mp(char c) {
    if (c == 'L' || c == 'R')
        return 1;
    return 2;
}
 
 
int main(void) {
    int n;
    char order[1001];
    int wood[100][100] = {0};
    
    scanf("%d", &n);
    scanf("%s", order);
    
    int len = strlen(order), i = 0, j = 0, ni = 0, nj = 0;
    for (int k = 0; k < len; k++) {
        switch (order[k]) {
            case 'L': nj--; break;
            case 'R': nj++; break;
            case 'U': ni--; break;
            default: ni++;
        }
        if (ni < 0 || ni >= n || nj < 0 || nj >= n) {
            ni = i;
            nj = j;
            continue;
        }
 
        wood[i][j] |= mp(order[k]);
        wood[ni][nj] |= mp(order[k]);
        
        i = ni;
        j = nj;
    }
    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)
            printf("%c", ".-|+"[wood[i][j]]);
        printf("\n");
    }
 
    return 0;
}