board → 3차원 [r][c][3]
visit → 2차원 [r][c] boolean
상어의 속력?
아직 이동하지 않은 상어(visit에서 false)라면, 해당 상어에 대한, 상어이동함수를 호출한다.
- 해당 장리에는, 이동을 마친 상어를 위치시킨다.
- board에 → 해당 상어 정보를 세팅
- visit → true로 세팅한다.
이동을 마친 상어라면 ( visit에서 true) → 두 상어의 크기를 비교 → 더 큰 상어를 남긴다.
board에 → 해당 상어 정보를 세팅
visit → true로 세팅
package coding;
import java.io.*;
import java.util.*;
public class Main{
/**
* king 은 0,0에 위치
* 상어들은 (1,1) 부터 (r,c)중에 위치한다.
* */
public static int[][][] board = new int[101][101][3];
public static boolean[][] visit = new boolean[101][101];
public static int gc,gr;
public static int king = 0; // 왕이 있는 열의 위치
public static int sum = 0;
public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static StringTokenizer st;
public static void setting() throws IOException {
st = new StringTokenizer(br.readLine());
gr = Integer.parseInt(st.nextToken());
gc = Integer.parseInt(st.nextToken());
int shark = Integer.parseInt(st.nextToken());
int lr, lc, ls, ld, lz;
for (int i = 0; i < shark; i++) {
st = new StringTokenizer(br.readLine());
lr = Integer.parseInt(st.nextToken());
lc = Integer.parseInt(st.nextToken());
ls = Integer.parseInt(st.nextToken());
// 방향 : 위(0), 아래(1) 오른쪽(2), 왼쪽(3)
ld = Integer.parseInt(st.nextToken()) - 1;
lz = Integer.parseInt(st.nextToken());
board[lr][lc][0] = lz;
board[lr][lc][1] = ls;
board[lr][lc][2] = ld;
}
}
public static void solve(){
for(king=1;king<=gc;king++){
// init visit
for(int r=1;r<=gr;r++) Arrays.fill(visit[r],false);
// System.out.println("================"+king+"번째 열================");
catchShark(king);
}
}
/**
* 왕이 column c에 있을 때 잡은 상어
* -> 0에 가장 가까운 row의 상어를 잡는다 -> board 를 0으로 세팅
* */
public static void catchShark(int c){
for(int r = 1 ; r <= gr; r++){
if(board[r][c][0] != 0){
// System.out.println("CATCH at ("+r+","+c+")");
sum += board[r][c][0];
board[r][c][0] = 0;
// printShark();
break;
}
}
// 상어의 이동을 위한 상어들 탐색 -> O(100x100x100)
for(int cr=1;cr <= gr;cr++){
for(int cc=1;cc <= gc;cc++){
if(board[cr][cc][0] != 0 && visit[cr][cc] == false){
shark_move(cr,cc);
}
}
}
// System.out.println("AFTER 1 SEC");
// printShark();
}
public static void printShark(){
for(int cr=1;cr <= gr;cr++){
for(int cc=1;cc <= gc;cc++){
System.out.printf("%5d ",board[cr][cc][0]);
}
System.out.println();
}
}
// 현재 (r,c)에 위치하는 상어를 움직이기
public static void shark_move(int r, int c){
int size = board[r][c][0], move = board[r][c][1],dir = board[r][c][2];
int nr =r ,nc = c, idx = 0;
board[r][c][0] = 0;
visit[r][c] = true;
int[] args = new int[2];
// 상어 움직이기 -> 규칙을 찾는게 필요해보임
// 각각에 대한 함수를 따로 선언함
switch(board[r][c][2]){
case 0:
up(r,c,args);
nr = args[0];
dir = args[1];
break;
case 1:
down(r,c,args);
nr = args[0];
dir = args[1];
break;
case 2:
right(r,c,args);
nc = args[0];
dir = args[1];
break;
case 3:
left(r,c,args);
nc = args[0];
dir = args[1];
break;
}
// System.out.println("SHARK MOVE ("+r+","+c+") --> ("+nr+","+nc+")");
afterSharkMove(nr,nc,size,move,dir);
}
/**
* args : 이동 후 상어의 위치 . 이동한 상어의 정보 ( 크기, 속도, 방향 )
* */
public static void afterSharkMove(int r, int c, int size, int move, int dir){
int pre = 0;
// 다른 상어가 존재 : board[r][c][0]이 0이 아닌 경우 ->
// while문을 한 것은 ,이전에 r,c에 위치하던 상어가 있었다면 이 상어를 이동시키고
// 이동시킨 후에도, 그 상어가 r,c에 위치하는 경우도 있을 수 있기 때문
while((pre=board[r][c][0]) != 0 ){
if(visit[r][c]){
// 다른 상어가 존재 && 이미 이동을 마친 상어
if( pre < size){
putShark(r,c,size,move,dir);
}
break;
}
// 아직 이 상어가 이동을 한 적 없다면 -> 이 상어는 이동시킨다.
else{
shark_move(r,c);
}
}
// 다른 상어가 존재 하지 않는 경우
if(pre == 0) {
// System.out.println("Main.afterSharkMove - when there's no other shark here.."+"r = " + r + ", c = " + c );
putShark(r, c, size, move, dir);
}
// System.out.println("Main.afterSharkMove");
// System.out.println("r = " + r + ", c = " + c + ", size = " + size + ", move = " + move + ", dir = " + dir);
// printShark();
}
public static void putShark(int r, int c,int size, int move, int dir){
visit[r][c] = true;
board[r][c][0] = size;
board[r][c][1] = move;
board[r][c][2] = dir;
}
public static void main(String[] args) throws IOException{
setting();
solve();
System.out.println(sum);
}
// right
// mod 를 사용하려다보니 필요한 과정이 생겼다.
public static void right(int r, int c, int[] args){
int cnt = board[r][c][1]; // 이동해야하는 칸의 수
// 이동 했을 때 방향
int d = (((c-1) + cnt)/(gc-1)) % 2; // 0 -> 방향 그대로 ( right )
// 이동 후 칸 인덱스
int idx = ((c-1) + cnt ) % (gc-1);
if(d == 0 ){
args[0] = idx+1;
args[1] = 2;
}else{
args[0] = gc-idx;
args[1] = 3;
}
}
// left
public static void left(int r, int c ,int[] args ){
int lc = gc - c;
int cnt = board[r][c][1]; // 이동해야하는 칸의 수
// 이동 했을 때 방향
int d = ((lc + cnt)/(gc-1)) % 2; // 0 -> 방향 그대로 ( left )
// 이동 후 칸 인덱스
int idx = (lc + cnt ) % (gc-1);
if(d ==0 ){
// 0, 1 , 2 ,3,4,5
args[0] = (gc-idx);
args[1] = 3;
}else{
// 5 4 3 2 1 0
args[0] = (idx+1);
args[1] = 2;
}
}
// left
public static void up(int r, int c ,int[] args){
int lr = gr - r;
int cnt = board[r][c][1]; // 이동해야하는 칸의 수
// 이동 했을 때 방향
int d = ((lr + cnt)/(gr-1)) % 2; // 0 -> 방향 그대로 (up )
// 이동 후 칸 인덱스
int idx = (lr + cnt ) % (gr-1);
if(d == 0 ){
// 0, 1 , 2 ,3,4,5
args[0]= (gr-idx);
args[1] = 0;
}else{
// 5 4 3 2 1 0
args[0]= (idx+1);
args[1] = 1;
}
}
public static void down(int r, int c,int[] args){
int cnt = board[r][c][1]; // 이동해야하는 칸의 수
// 이동 했을 때 방향
int d = (((r-1) + cnt)/(gr-1)) % 2; // 0 -> 방향 그대로 (down )
// 이동 후 칸 인덱스
int idx = ((r-1) + cnt ) % (gr-1);
if(d ==0 ){
// 0, 1 , 2 ,3,4,5
args[0]= idx+1;
args[1] = 1;
}else{
// 5 4 3 2 1 0
args[0]= gr-(idx);
args[1]=0;
}
}
}