반응형
간단한 구현문제이다.
코드에 대한 욕심때문에 방향에 대한 dx,dy만 정해놓고 나머지는 회전하면서 전개해 나가려고 코드를 작성하였는데, 방향에 따른 왼쪽 오른쪽 구분이 일관되게 진행할 수 없어서 중간에 모래가 사라지게 되었다.
잘못된 코드는 아래 첨부하겠다.
더보기
import jdk.swing.interop.SwingInterOpUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[][] grid;
static int[] dr = {0, 1, 0, -1};
static int[] dc = {-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());
N = Integer.parseInt(st.nextToken());
grid = new int[N + 4][N + 4];//가장자리부분만 따로더한다.
for (int i = 2; i < N + 2; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 2; j < N + 2; j++) {
grid[i][j] = Integer.parseInt(st.nextToken());
}
}
int sr = N / 2 + 1 + 2 - 1;
int sc = N / 2 + 1 + 2 - 1;
int d = 0;
loop:
while (sr >= 2 && sc >= 2 && sr <= N - 1 && sc <= N - 1) {//토네이도 위치 그리드 내부일때
for (int k = 1; k <= N; k++) {
//두번씩 k칸이동
for (int i = k == N ? 2 : 1; i <= k; i++) {//마지막 행일떄는 한칸 덜 가야함
sr += dr[d];
sc += dc[d];
tornado(sr, sc, d);
grid[sr][sc] = 0;
}
d = directionPlus(d + 1);
if (k == N) break loop;//마지막시행 종료
for (int i = 1; i <= k; i++) {
sr += dr[d];
sc += dc[d];
tornado(sr, sc, d);
grid[sr][sc] = 0;
}
d = directionPlus(d + 1);
}
}
int answer = 0;
for (int i = 0; i < N + 4; i++) {
System.out.println();
for (int j = 0; j < N + 4; j++) {
System.out.print(grid[i][j] + " ");
if (i >= 2 && j >= 2 && i <= N + 1 && j <= N + 1) continue;
answer += grid[i][j];
}
}
System.out.println("\n\n" + answer);
}
static void tornado(int sr, int sc, int d) {
int sand = grid[sr][sc];
if (sand == 0) return;
int comsumed = 0;
//위두개---------------------
int newdr = directionPlus(d + 3);
int newdc = directionPlus(d + 3);
comsumed += (int) (sand * 0.07);
grid[sr + dr[newdr]][sc + dc[newdc]] += (int) (sand * 0.07);
comsumed += (int) (sand * 0.02);
grid[sr + 2 * dr[newdr]][sc + 2 * dc[newdc]] += (int) (sand * 0.02);
//위오른쪽
newdr = directionPlus(d + z);
newdc = directionPlus(d + 2);
comsumed += (int) (sand * 0.01);
grid[sr + dr[newdr]][sc + dc[newdc]] += (int) (sand * 0.01);
//위왼쪽
newdr = directionPlus(d + 3);
newdc = directionPlus(d);
comsumed += (int) (sand * 0.10);
grid[sr + dr[newdr]][sc + dc[newdc]] += (int) (sand * 0.10);
//아래두개---------------------
newdr = directionPlus(d + 1);
newdc = directionPlus(d + 1);
comsumed += (int) (sand * 0.07);
grid[sr + dr[newdr]][sc + dc[newdc]] += (int) (sand * 0.07);
comsumed += (int) (sand * 0.02);
grid[sr + 2 * dr[newdr]][sc + 2 * dc[newdc]] += (int) (sand * 0.02);
//아래오른쪽
newdc = directionPlus(d + 2);
comsumed += (int) (sand * 0.01);
grid[sr + dr[newdr]][sc + dc[newdc]] += (int) (sand * 0.01);
//아래왼쪽
newdc = directionPlus(d);
comsumed += (int) (sand * 0.10);
grid[sr + dr[newdr]][sc + dc[newdc]] += (int) (sand * 0.10);
//왼왼쪽---------------
comsumed += (int) (sand * 0.05);
grid[sr + 2 * dr[d]][sc + 2 * dc[d]] += (int) (sand * 0.05);
grid[sr + dr[d]][sc + dc[d]] += sand - comsumed;
}
static int directionPlus(int newd) {
return (newd + 4) % 4;
}
}
아래는 모든 방향에 따른 모래가 퍼지는 방향을 정의해놓은 후에 작성한 코드이다.
코드출처 : https://alwaysbemoon.tistory.com/225
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[][] map;
static int[] dx = {0, 1, 0, -1}; //토네이토의 x 이동 방향
static int[] dy = {-1, 0, 1, 0}; //토네이토의 y 이동 방향
static int[] dc = {1, 1, 2, 2}; // 토네이도의 각 방향으로 이동하는 횟수
static int[][] dsx = {
{-1, 1, -2, -1, 1, 2, -1, 1, 0},
{-1, -1, 0, 0, 0, 0, 1, 1, 2}, //모래가 퍼지는 x방향
{1, -1, 2, 1, -1, -2, 1, -1, 0},
{1, 1, 0, 0, 0, 0, -1, -1, -2}
};
static int[][] dsy = {
{1, 1, 0, 0, 0, 0, -1, -1, -2},
{-1, 1, -2, -1, 1, 2, -1, 1, 0}, //모래가 퍼지는 y방향
{-1, -1, 0, 0, 0, 0, 1, 1, 2},
{1, -1, 2, 1, -1, -2, 1, -1, 0}
};
static int[] sandRatio = {1, 1, 2, 7, 7, 2, 10, 10, 5};
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
N = Integer.parseInt(br.readLine().trim());
map = new int[N][N];
for (int r = 0; r < N; r++) {
st = new StringTokenizer(br.readLine(), " ");
for (int c = 0; c < N; c++) {
map[r][c] = Integer.parseInt(st.nextToken());
}
}
int result = calculateOutSand(N / 2, N / 2);
bw.write(String.valueOf(result));
bw.flush();
}
//현재위치에서 이동 -> 이동한 위치의 모래 뿌리기 -> 이동한위치를 현재위치로 업데이트
static int calculateOutSand(int x, int y) {
int totalOutSand = 0;
int currentX = x;
int currentY = y;
while (true) {
for (int d = 0; d < 4; d++) {
for (int moveCount = 0; moveCount < dc[d]; moveCount++) {
//현재위치에서 이동
int nextX = currentX + dx[d];
int nextY = currentY + dy[d];
if (nextX < 0 || nextY < 0 || nextX >= N || nextY >= N) {
return totalOutSand;
}
//이동한 위치의 모래 뿌리기
int sand = map[nextX][nextY];
map[nextX][nextY] = 0;
int spreadTotal = 0;
for (int spread = 0; spread < 9; spread++) {
int sandX = nextX + dsx[d][spread];
int sandY = nextY + dsy[d][spread];
int spreadAmount = (sand * sandRatio[spread]) / 100;
if (sandX < 0 || sandX >= N || sandY < 0 || sandY >= N) {
totalOutSand += spreadAmount;
} else {
map[sandX][sandY] += spreadAmount;
}
spreadTotal += spreadAmount;
}
//알파
int alphaX = nextX + dx[d];
int alphaY = nextY + dy[d];
int alphaAmount = sand - spreadTotal;
if (alphaX < 0 || alphaX >= N || alphaY < 0 || alphaY >= N) {
totalOutSand += alphaAmount;
} else {
map[alphaX][alphaY] += alphaAmount;
}
//이동한 위치를 현재위치로 업데이트
currentX = nextX;
currentY = nextY;
}
}
//횟수 업데이트
for (int index = 0; index < 4; index++) {
dc[index] += 2;
}
}
}
}
반응형
'코딩테스트 > Java' 카테고리의 다른 글
[JAVA] 프로그래머스 음양 더하기 (0) | 2021.10.27 |
---|---|
[JAVA] 프로그래머스 약수의 개수와 덧셈 (0) | 2021.10.27 |
[JAVA] 백준 새로운게임2 (0) | 2021.10.20 |
[JAVA] 백준 게리맨더링2 (0) | 2021.10.05 |
[JAVA] 백준 어른상어 (0) | 2021.10.05 |