https://www.acmicpc.net/problem/20057
20057번: 마법사 상어와 토네이도
마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을
www.acmicpc.net
저는 해당 문제를 DFS를 이용해 해결하였습니다.
저는 방향을 왼쪽, 아래쪽, 오른쪽, 위쪽 순으로 인덱스를 매겼습니다.
그리고 이 방향이 모듈러 연산을 했을 때 나눠떨어지지 않으면 길이를 하나씩 늘려 주었습니다.
모래의 비율로 퍼저나가는 것은 하드코딩하였습니다. 매핑시켜 for문으로 만들고 싶었지만, 괜찮은 방법이 떠오르지 않아 하드코딩하였습니다.
package BOJ.Simulation;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.function.Function;
public class BOJ_20057 {
private static final int[] dy = {0,1,0,-1};
private static final int[] dx = {-1,0,1,0};
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine()," ");
Function<String,Integer> stoi = Integer::parseInt;
int n = stoi.apply(st.nextToken());
int[][] map = new int[n][n];
int y = n/2;
int x= n/2;
for(int i = 0 ; i < n ; i++){
st = new StringTokenizer(br.readLine());
for(int j = 0 ; j < n ; j++){
map[i][j] = stoi.apply(st.nextToken());
}
}
int dir = 0;
int dis = 1;
int result = dfs(y,x,map,dir,dis,n);
System.out.println(result);
}
private static int dfs(int y, int x, int[][] map,int dir, int dis,int n) {
if(y == 0 && x == 0){
return 0;
}
int ny = y;
int nx = x;
int result = 0;
for(int i = 0 ; i < dis ; i++){
// System.out.println(ny+" "+nx+" "+dir+" "+i);
if(ny == 0 && nx == 0){
break;
}
ny += dy[dir];
nx += dx[dir];
result += moveSend(ny,nx,dir,map,n);
}
if(dir % 2 != 0){
dis++;
}
result += dfs(ny,nx,map,(dir+1)%4,dis,n);
return result;
}
private static final int LEFT = 3;
private static final int RIGHT = 1;
private static int moveSend(int y, int x, int dir, int[][] map,int n) {
int result = 0;
int used = 0;
int amount = map[y][x];
if(amount == 0){
return 0;
}
int nowDir = dir;
int leftDir = (dir + LEFT) % 4;
int rightDir = (dir + RIGHT) % 4;
int ny = y + 2 * dy[nowDir];
int nx = x + 2 * dx[nowDir];
int nowAmount = amount * 5 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y + dy[nowDir] + dy[leftDir];
nx = x + dx[nowDir] + dx[leftDir];
nowAmount = amount * 10 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y + dy[nowDir] + dy[rightDir];
nx = x + dx[nowDir] + dx[rightDir];
nowAmount = amount * 10 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y + dy[leftDir];
nx = x + dx[leftDir];
nowAmount = amount * 7 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y + dy[rightDir];
nx = x + dx[rightDir];
nowAmount = amount * 7 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y + 2 * dy[leftDir];
nx = x + 2 * dx[leftDir];
nowAmount = amount * 2 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y + 2 * dy[rightDir];
nx = x + 2 * dx[rightDir];
nowAmount = amount * 2 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y - dy[nowDir] + dy[leftDir];
nx = x - dx[nowDir] + dx[leftDir];
nowAmount = amount * 1 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y - dy[nowDir] + dy[rightDir];
nx = x - dx[nowDir] + dx[rightDir];
nowAmount = amount * 1 / 100;
used += nowAmount;
result += move(ny,nx,map,n,nowAmount);
ny = y + dy[nowDir];
nx = x + dx[nowDir];
nowAmount = amount - used;
result += move(ny,nx,map,n,nowAmount);
return result;
}
private static int move(int y,int x,int[][]map,int n,int amount){
if(checkBound(y,x,n)){
map[y][x] += amount;
return 0;
}else{
return amount;
}
}
private static boolean checkBound(int y,int x, int n){
if(y < 0 || y >= n || x < 0 || x >= n ){
return false;
}
return true;
}
}
'알고리즘' 카테고리의 다른 글
백준 15685 드래곤 커브 (JAVA) (0) | 2022.03.31 |
---|---|
백준 15684번 사다리 조작 (JAVA) (0) | 2022.03.30 |
백준 20056번 마법사 상어와 파이어볼 (JAVA) (0) | 2022.03.28 |
백준 2174번 로봇 시뮬레이션 (JAVA) (0) | 2022.03.27 |
백준 19236번 청소년 상어(JAVA) (0) | 2022.03.26 |