[백준] 17143 낚시왕

문제보기

  1. 상어 리스트를 따로 배열로 구현(생사여부도 인스턴스 변수로 표현되어서 굳이 동적배열 쓸 필욘 없다… 나는 그냥 생각없이 짰을 뿐)
  2. 매 초마다 맵 새로 갱신
  3. 벽에 부딪히는 부분만 주의해줄 것
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
// 상어 클래스
class Shark{
	int r; // 행
	int c; // 열
	int s; // 스피드
	int d; // 방향
	int z; // 크기
	boolean alive; // 생사여부
	Shark(int r, int c, int s, int d, int z){
		this.r = r;
		this.c = c;
		this.s = s;
		this.d = d;
		this.z = z;
		this.alive = true;
	}
	
}
public class Main {
  // 방향좌표. 순서대로 상하우좌
	static int[] dx = {-1, 1, 0, 0}; 
	static int[] dy = {0, 0, 1, -1};

	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int r = Integer.parseInt(st.nextToken());
		int c = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		List<Shark> list = new ArrayList<>(); // 상어 리스트를 받을 배열 - 정적배열 써도 됨
		int[][] map = new int[r][c]; // 상어 현황
		for(int i = 0 ; i < r ; i++) {
			Arrays.fill(map[i], -1); // -1로 초기화 
		}
		for(int i = 0 ; i < m ; i++) {
			st = new StringTokenizer(br.readLine());
			int rr = Integer.parseInt(st.nextToken())-1; // 0-index가 편해서..
			int cc = Integer.parseInt(st.nextToken())-1;
			// 상어 추가
      			list.add(new Shark(rr, cc,
			Integer.parseInt(st.nextToken()), 
			Integer.parseInt(st.nextToken())-1, 
			Integer.parseInt(st.nextToken())));
			// 맵에 어떤 상어가 있는지 인덱스값을 넣어줌
      			map[rr][cc] = i;
		}
		// 낚시왕이 낚은 상어 크기의 합
		int sum = 0;
		
   		 // 매초 열을 한 칸씩 이동한다
		for(int col = 0 ; col < c ; col++) {
     			 // 해당 열의 제일 위에 있는 상어를 잡는다
			for(int row = 0 ; row < r ; row++) {
				if(map[row][col] != -1) {
					int idx = map[row][col];
					list.get(idx).alive = false; // 죽었음을 표시
					sum += list.get(idx).z; // 크기 합에 더해줌
					map[row][col] = -1; // 맵에서 삭제
					break; // 한마리만 잡고 나와야 함
				}
			}
			
      			// 상어 떼 이동
			for(int i = 0 ; i < m ; i++) {
        			// 살아있는 상어만 움직일 수 있다
				if(list.get(i).alive) {
					Shark shark = list.get(i);
         				 // 상어가 움직일 방향
					int dr = dx[shark.d];
					int dc = dy[shark.d];
          				// 상어의 다음 좌표
					int nr = shark.r; int nc = shark.c;
          				// 스피드 만큼 초당 움직여야 함
					for(int t = 0 ; t < shark.s ; t++) {			
						if(dr == 0) { // 만약 좌/우로 움직이는 상어라면
             						 // 0에서 더 왼쪽으로 가려하거나, 끝칸에서 더 오른쪽으로 가려한다면
							if((nc == 0 && dc == -1) || (nc == c-1 && dc == 1)) {
								dc *= -1; // 방향을 바꿔주고
							}
							nc += dc;	// 다음칸으로 옮겨주자					
						}else { // 만약 상/하로 움직이는 상어라면
              						// 위에랑 같은 원리다
							if((nr == 0 && dr == -1) || (nr == r-1 && dr == 1)) {
								dr *= -1;
							}
							nr += dr;
						}
					}
					// 최종 좌표로 갱신해준다
					list.get(i).r = nr;
					list.get(i).c = nc;
          				// 방향값도 새로 갱신해주자
					if(dr == 0) {
						if(dc == 1) { // 오른쪽 방향 일 때
							list.get(i).d = 2;
						}else { // 왼쪽 방향일 때
							list.get(i).d = 3;
						}
					}else if(dr == 1){ // 아래 방향일 때
						list.get(i).d = 1;
					}else { // 윗 방향일 때
						list.get(i).d = 0;
					}
				}
			}
			// 맵 새로 갱신
			map = new int[r][c];
			for(int row = 0 ; row < r ; row++) {
				Arrays.fill(map[row], -1); // -1로 초기화
			}
      			// 상어 위치를 다시 맵에 찍어준다
			for(int i = 0 ; i < m ; i++) {
				if(list.get(i).alive) { // 살아 있는 상어에 한해
					Shark shark = list.get(i);
					// 만약 그 칸이 비어있다면
					if(map[shark.r][shark.c] == -1) {
						map[shark.r][shark.c] = i; // 상어의 인덱스를 넣어 표시한다
					}else { // 이미 다른 상어가 해당 칸에 존재한다면
						if(list.get(map[shark.r][shark.c]).z < shark.z) { // 내가 걔보다 쎄다면
							list.get(map[shark.r][shark.c]).alive = false; // 걘 죽는다
							map[shark.r][shark.c] = i; // 그리고 내 인덱스로 덮는다
						}else { // 내가 걔보다 약하다면
							list.get(i).alive = false; // 내가 죽는다
						}
					}
				}
			}
		}
		System.out.println(sum); // 출력
	}
}


Tags:

Categories:

Updated:

Comments