Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

Life Engineering

[BOJ 20057] 마법사 상어와 토네이도 (Java) 본문

Problem Solving

[BOJ 20057] 마법사 상어와 토네이도 (Java)

흑개 2022. 4. 1. 17:25

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

 

20057번: 마법사 상어와 토네이도

마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을

www.acmicpc.net

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main_BOJ_20057 {
	static double[][] left= {{0,0,0.02,0,0},{0,0.1,0.07,0.01,0},{0.05,0,0,0,0}, {0,0.1,0.07,0.01,0},{0,0,0.02,0,0}};
	static double[][] right=new double[5][5]; 
	static double[][] up=new double[5][5];
	static double[][] down=new double[5][5];
	static int[][] center= {{2,3},{1,2},{2,1},{3,2}};
	static int[][] map;
	static int[] dr= {0,1,0,-1};	//좌 하 우 상
	static int[] dc= {-1,0,1,0};
	static int len=2;
	static int count=0;
	static int N;
	static int r, c, dir;
	static int answer=0;
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st=null;
		N=Integer.parseInt(br.readLine());
		map=new int[N][N];
		for (int i = 0; i <N; i++) {
			st=new StringTokenizer(br.readLine());
			for (int j = 0; j < N; j++) {
				map[i][j]=Integer.parseInt(st.nextToken());
			}
		}
		r=N/2;
		c=N/2;
		dir=0;
		for (int i=0; i<5; i++) {
			for (int j=0; j<5; j++) {
				up[i][j]=left[4-j][i];	
				down[i][j]=left[j][4-i];
				right[i][j]=left[4-i][4-j];
			}
		}
		for (int i=2; i<=N; i++) {
			move(r, c, i, dir);	//r,c 갱신
			move(r, c, i, dir);
			if (i==N) {
				move(r, c, i, dir);
			}
		}
		System.out.println(answer);

	}
	private static void move(int r2, int c2, int cnt, int dir2) {
		double[][] temp=directions(dir2);
		for (int i=0; i<cnt-1; i++) {		//한번 흩날리기 (시작점: r2, c2)
			int move_r=center[dir2][0]-r2;
			int move_c=center[dir2][1]-c2;
			int y_r=r2+dr[dir2];
			int y_c=c2+dc[dir2];
			int sum=map[y_r][y_c];
			for (int j=0; j<5; j++) {		//a일때 경계 벗어날 때 체크
				for (int k=0; k<5; k++) {
					if (temp[j][k]>0) {
						int sand=(int)(map[y_r][y_c]*temp[j][k]);
						if (isOutside(j-move_r, k-move_c)) {
							answer+=sand;
							sum-=sand;
						}
						else {
							map[j-move_r][k-move_c]+=sand;
							sum-=sand;
						}
					}
				}
			}
			int a_r=y_r+dr[dir2];
			int a_c=y_c+dc[dir2];
			if (isOutside(a_r, a_c)) {
				answer+=sum;
			}
			else {
				map[a_r][a_c]+=sum;
			}
			map[y_r][y_c]=0;
			r2=y_r;
			c2=y_c;
		}
		r=r2;
		c=c2;
		dir=(dir2+1)%4;
	}
	
	private static boolean isOutside(int r, int c) {
		return r<0 || c<0 || r>=N || c>=N;
	}
	
	private static double[][] directions(int i) {
		if (i==0) return left;
		else if (i==1) return down;
		else if (i==2) return right;
		else return up;
	}

}

시뮬레이션 문제.. 은근 까다로웠다.

 

흩날리는 비율을 표시한 표를 각각 오른쪽으로 이동, 위쪽으로 이동, 아래쪽으로 이동할 경우를 고려해서 회전시켜준다.

평행이동처럼 구현했다. 이동 방향에 따라 흩날리는 비율을 표시한 표를 map과 매칭시켜, 경계를 넘어설 경우 answer 값에 저장하고 그 외의 경우에는 문제의 조건대로 그대로 구현했다..

 

평행이동+회전을 이용해서 풀었다.