[문제풀이-백준] 20057. 마법사 상어와 토네이도

62334 단어 백준백준

풀이

시뮬레이션

처음 생각했던 방법

  • 모래를 계산할 때, 좌표, 방향에 따라 모두 if 분기를 하려고 하니 200라인이 넘어감

개선 방법

  • 델타를 이용하되 dy,dx로 쪼갤 것

  • 총 방향은 4개이고, 모래가 날아가는 횟수는 10이므로 델타는 [4][10]이면 된다.

풀이 방법

  • 토네이도 이동 함수

    • 무조건 꺾어지려는 성질 이용
  • 이동 방향에 따라 날아가는 모래 양 계산 함수

  • 모래가 밖으로 날아갈 때마다 answer에 추가

코드

import math

def move(y,x,d,ans):
    total = 0
    for dir in range(9):
        ny, nx = y + dy[d][dir], x + dx[d][dir]
        # 1%
        if dir == 0 or dir == 1:
            sand = math.floor(links[y][x] * 0.01)
        # 2%
        elif dir == 2 or dir == 3:
            sand = math.floor(links[y][x] * 0.02)
        # 7%
        elif dir == 4 or dir == 5:
            sand = math.floor(links[y][x] * 0.07)
        # 10%
        elif dir == 6 or dir == 7:
            sand = math.floor(links[y][x] * 0.1)
        # 5%
        else:
            sand = math.floor(links[y][x] * 0.05)

        if 0 <= ny < N and 0 <= nx < N:
            links[ny][nx] += sand
        else:
            ans += sand
        total += sand
    # 나머지
    ny, nx = y + dy[d][9], x + dx[d][9]
    links[y][x] -= total
    if 0 <= ny < N and 0 <= nx < N:
        links[ny][nx] += links[y][x]
    else:
        ans += links[y][x]
    links[y][x] = 0

    return ans


def tornado(by,bx,bd):
    nd = (bd+1) % 4
    ny,nx = by+direct[nd][0],bx+direct[nd][1]
    # if 0 <= ny < N and 0 <= nx < N:
    if visited[ny][nx]:
        ny,nx,nd = by+direct[bd][0],bx+direct[bd][1],bd
        visited[ny][nx] = True
        return ny,nx,nd
    else:
        visited[ny][nx] = True
        return ny,nx,nd


N = int(input())
links = [list(map(int,input().split())) for _ in range(N)]
y = x = N // 2
d = 3
answer = 0
direct = [(0,-1),(1,0),(0,1),(-1,0)]
visited = [[False]*N for _ in range(N)]
visited[y][x] = True
dy = [
    [-1,1,-2,2,-1,1,-1,1,0,0], # 10 # 1%,2%,7%,10%,5%,나머지
    [-1,-1,0,0,0,0,1,1,2,1],
    [-1,1,-2,2,-1,1,-1,1,0,0],
    [1,1,0,0,0,0,-1,-1,-2,-1],
]
dx = [
    [1,1,0,0,0,0,-1,-1,-2,-1],
    [-1,1,-2,2,-1,1,-1,1,0,0],
    [-1,-1,0,0,0,0,1,1,2,1],
    [-1,1,-2,2,-1,1,-1,1,0,0],
]
while True:
    y,x,d = tornado(y,x,d)
    answer = move(y,x,d,answer)
    if (y,x) == (0,0):
        break
print(answer)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main20057_마법사상어와토네이도 {
	private static int N;
	private static int[][] links;
	private static boolean[][] visited;
	private static int[][] direct = {
			{0,-1},
			{1,0},
			{0,1},
			{-1,0},
	};
	private static int[][] dy = {
			{-1,1,-2,2,-1,1,-1,1,0,0}, // 10 # 1%,2%,7%,10%,5%,나머지
		    {-1,-1,0,0,0,0,1,1,2,1},
		    {-1,1,-2,2,-1,1,-1,1,0,0},
		    {1,1,0,0,0,0,-1,-1,-2,-1},
	};
	private static int[][] dx = {
			{1,1,0,0,0,0,-1,-1,-2,-1},
		    {-1,1,-2,2,-1,1,-1,1,0,0},
		    {-1,-1,0,0,0,0,1,1,2,1},
		    {-1,1,-2,2,-1,1,-1,1,0,0},
	};
	public static int move(int y, int x, int d, int ans) {
		int total = 0;
		int sand = 0;
		int ny, nx;
	    for (int dir=0; dir<9; dir++) {
	        ny = y + dy[d][dir];
	        nx = x + dx[d][dir];
	        if (dir == 0 || dir == 1) {
	        	// 1%
	            sand = (int) Math.floor(links[y][x] * 0.01);
	        } else if (dir == 2 || dir ==3) {
	        	// 2%
	            sand = (int) Math.floor(links[y][x] * 0.02);
	        } else if (dir ==4 || dir == 5) {
	        	// 7%
	            sand = (int) Math.floor(links[y][x] * 0.07);
	        } else if (dir == 6 || dir == 7) {
	        	// 10%
	            sand = (int) Math.floor(links[y][x] * 0.1);
	        } else {
	        	// 5%
	        	sand = (int) Math.floor(links[y][x] * 0.05);
	        }
	            

	        if (0 <= ny && ny < N && 0 <= nx && nx < N) {
	            links[ny][nx] += sand;
	        } else {
	            ans += sand;
	        }
	        total += sand;
	        
	    }
	    // 나머지
	    ny = y + dy[d][9];
	    nx = x + dx[d][9];
	    links[y][x] -= total;
	    if (0 <= ny && ny < N && 0 <= nx && nx < N) {
	        links[ny][nx] += links[y][x];
	    } else {
	        ans += links[y][x];
	    }
	    links[y][x] = 0;
	    
	    return ans;
	}
	public static int[] tornado(int by, int bx, int bd) {
		int nd = (bd+1) % 4;
		int ny = by+direct[nd][0];
		int nx = bx+direct[nd][1];
		int[] result = new int[4];
	    if (visited[ny][nx]) {
	        ny = by+direct[bd][0];
	        nx = bx+direct[bd][1];
	        nd = bd;
	    }
	    visited[ny][nx] = true;
		result[0] = ny;
		result[1] = nx;
		result[2] = nd;
		return result;
	}
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine()," ");
		N = Integer.parseInt(st.nextToken());
		links = new int[N][N];
		for (int i=0; i<N; i++) {
			st = new StringTokenizer(br.readLine()," ");
			for (int j=0; j<N; j++) {
				links[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		int y = N / 2;
		int x = N / 2;
		int d = 3;
		int answer = 0;
		visited = new boolean[N][N];
		visited[y][x] = true;
		int[] result = new int[] {y,x,d};
		while (true) {
			result = tornado(result[0],result[1],result[2]);
		    answer = move(result[0],result[1],result[2],answer);
		    if (result[0] == 0 && result[1] == 0) {
		    	break;
		    }
		}
		System.out.println(answer);		
	}

}

좋은 웹페이지 즐겨찾기