[boj] 23288 주사위 굴리기 2

serotonins·2022년 9월 17일

Coding Q

목록 보기
1/17

C언어로 시작해서 실패를 맛보고
JAVA로 단련을 거듭하던 어느 날 다시 시도해봤을 때 결국 풀어낸 문제

코드를 치기 전 생각을 해야한다.
모든 상황을 고려하고 미리 설계를 한 뒤 가장 나중에 코드를 치자.

주사위의 여섯 면과 방향, 위치를 담은 객체를 만든 게 좋았던 거 같다.
굴리는 방향에 따라 어떻게 달라지는지 상상을 하는 게 안 그려졌었는데 그림도 그려보고, 문제 풀이를 여러번 해본 경험이 쌓이니까 해낼 수 있었어.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	public static int[][] dr = new int[][] {{0,1,0,-1}, {1,0,-1,0}};
	public static int n;
	public static int m;
	public static int[][] pan;
	public static int result = 0;
	
	public static class dice {
		static int up = 1;
		static int north = 2;
		static int east = 3;
		static int south = 5;
		static int west = 4;
		static int down = 6;
		
		static int y = 0;
		static int x = 0;
		
		static int direc = 0;
	}
	
	public static boolean isOut(int y, int x) {
		if (y < 0 || y >= n) return true;
		if (x < 0 || x >= m) return true;
		return false;
	}
	
	public static void rollDice() {
		if (dice.direc == 0 && isOut(dice.y, dice.x+1)) dice.direc = 2;
		if (dice.direc == 1 && isOut(dice.y+1, dice.x)) dice.direc = 3;
		if (dice.direc == 2 && isOut(dice.y, dice.x-1)) dice.direc = 0;
		if (dice.direc == 3 && isOut(dice.y-1, dice.x)) dice.direc = 1;
		
		
		if (dice.direc == 0) {
			dice.x++;
			
			int temp = dice.up;
			dice.up = dice.west;
			dice.west = dice.down;
			dice.down = dice.east;
			dice.east = temp;
		} else if (dice.direc == 1) {
			dice.y++;
			
			int temp = dice.up;
			dice.up = dice.north;
			dice.north = dice.down;
			dice.down = dice.south;
			dice.south = temp;
		} else if (dice.direc == 2) {
			dice.x--;
			
			int temp = dice.up;
			dice.up = dice.east;
			dice.east = dice.down;
			dice.down = dice.west;
			dice.west = temp;
		} else {
			dice.y--;
			
			int temp = dice.up;
			dice.up = dice.south;
			dice.south = dice.down;
			dice.down = dice.north;
			dice.north = temp;
		}
	}
	
	public static void scoreCal() {
		int pSco = pan[dice.y][dice.x];
		if (dice.down > pSco) dice.direc = (dice.direc + 1) % 4;
		else if (dice.down < pSco) dice.direc = (dice.direc + 3) % 4;
		
		Queue<int[]> que = new LinkedList<int[]>();
		boolean[][] visit = new boolean[n][m];
		que.add(new int[] {dice.y, dice.x});
		visit[dice.y][dice.x] = true;
		int cnt = 1;
		
		while (!que.isEmpty()) {
			int[] now = que.poll();
			for (int i = 0; i < 4; i++) {
				int goy = now[0] + dr[0][i];
				int gox = now[1] + dr[1][i];
				if (isOut(goy, gox) || pan[goy][gox] != pSco || visit[goy][gox]) continue;
				visit[goy][gox] = true;
				que.add(new int[] {goy, gox});
				cnt++;
			}
		}
		
		result += cnt * pSco;
	}
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		/*
		 * 1. 이동방향으로 한칸(끝칸이라면 이동방향 반대로 바꾼 후 한칸)
		 * 2. 도착한 칸 점수(B*주변에B영역크기) 획득
		 * 3. 주사위 아랫면 A 칸 B
		 * 	A>B 시계, A=B 변화 x, A<B 반시계 
		 */
		st = new StringTokenizer(br.readLine());
		n = Integer.parseInt(st.nextToken());
		m = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken()); // 이동 횟수
		
		pan = new int[n][m];
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < m; j++) {
				pan[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		
		for (int idong = 0; idong < k; idong++) {
			rollDice();
			scoreCal();
		}
		
		System.out.println(result);
	}
}

과거의 내가 시도했던 C언어 풀이는 아래와 같다.


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <malloc.h>

int d = 1, count = 0; // 방향, 총 획득 점수
int x = 1, y = 1;
int N, M, K; // 세로, 가로, 횟수
int kount = 0; // 방문 횟수 카운트
int dice[7];
int map[21][21], dojang[21][21];

void south() {
    dice[6] = dice[3];
    dice[3] = dice[2];
    dice[2] = dice[1];
    dice[1] = dice[0];
    dice[0] = dice[6];
    y++;
}

void north() {
    dice[6] = dice[0];
    dice[0] = dice[1];
    dice[1] = dice[2];
    dice[2] = dice[3];
    dice[3] = dice[6];
    y--;
}

void east() {
    dice[6] = dice[1];
    dice[1] = dice[4];
    dice[4] = dice[3];
    dice[3] = dice[5];
    dice[5] = dice[6];
    x++;
}

void west() {
    dice[6] = dice[1];
    dice[1] = dice[5];
    dice[5] = dice[3];
    dice[3] = dice[4];
    dice[4] = dice[6];
    x--;
}

void direction() {
    if (dice[3] > map[x][y]) {
        if (d >= 4) d = 1;
        else d++;
    } else if (dice[3] < map[x][y]) {
        if (d <= 1) d = 4;
        else d--;
    }

    if (x == M && d == 1) d = 3;
    if (x == 1 && d == 3) d = 1;
    if (y == N && d == 2) d = 4;
    if (y == 1 && d == 4) d = 2;
}

void wasd(int a, int b) {
    if ((a + 1 <= M) && (dojang[a + 1][b] == 0)) {
        if (map[a + 1][b] == map[x][y]) {
            dojang[a + 1][b] = 1;
            wasd(a + 1, b);
        } else dojang[a + 1][b] = 2;
    }

    if ((b + 1 <= N) && (dojang[a][b + 1] == 0)) {
        if (map[a][b + 1] == map[x][y]) {
            dojang[a][b + 1] = 1;
            wasd(a, b + 1);
        } else dojang[a + 1][b] = 2;
    }

    if ((a - 1 >= 1) && (dojang[a - 1][b] == 0)) {
        if (map[a - 1][b] == map[x][y]) {
            dojang[a - 1][b] = 1;
            wasd(a - 1, b);
        } else dojang[a - 1][b] = 2;
    }

    if ((b - 1 >= 1) && (dojang[a][b - 1] == 0)) {
        if (map[a][b - 1] == map[x][y]) {
            dojang[a][b - 1] = 1;
            wasd(a, b - 1);
        } else dojang[a][b - 1] = 2;
    }
}

void jumsu(int x, int y) {
    for (int i = 1; i <= M; i++)
        for (int j = 1; j <= N; j++)
            dojang[i][j] = 0;

    dojang[x][y] = 1;
    wasd(x, y);

    int s = 0;
    for (int i = 1; i <= M; i++)
        for (int j = 1; j <= N; j++)
            if (dojang[i][j] == 1) s++;

    count = count + s * map[x][y];
}

void game(int d) {
    if (kount >= K) return;

    if (d == 1) east();
    else if (d == 2) south();
    else if (d == 3) west();
    else if (d == 4) north();

    kount++;
    jumsu(x, y); // 점수 획득
    direction(); // 방향 설정
    game(d);
}

int main() {
    dice[0] = 2;
    dice[1] = 1; //윗면
    dice[2] = 5;
    dice[3] = 6; //바닥면
    dice[4] = 4; //좌
    dice[5] = 3; //우

    scanf("%d %d %d ", &N, &M, &K);

    for (int j = 1; j <= N; j++)
        for (int i = 1; i <= M; i++)
            scanf("%d ", &map[i][j]);

    game(1);

    printf("%d", count);

    getchar();
    getchar();
    getchar();

    return 0;
}

0개의 댓글