πŸ”‘ Problem Solving/πŸ’» Samsung SW Expert

[JAVA] BOJ λ°±μ€€ 17143 λ‚šμ‹œμ™•

snowball🐰 2023. 2. 17. 17:13

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

 

17143번: λ‚šμ‹œμ™•

λ‚šμ‹œμ™•μ΄ 상어 λ‚šμ‹œλ₯Ό ν•˜λŠ” 곳은 크기가 R×C인 격자판으둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. 격자판의 각 칸은 (r, c)둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. r은 ν–‰, cλŠ” 열이고, (R, C)λŠ” μ•„λž˜ κ·Έλ¦Όμ—μ„œ κ°€μž₯ 였λ₯Έμͺ½ μ•„λž˜μ— μžˆλŠ” 칸이닀.

www.acmicpc.net

문제

λ‚šμ‹œμ™•μ΄ 상어 λ‚šμ‹œλ₯Ό ν•˜λŠ” 곳은 크기가 R×C인 격자판으둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. 격자판의 각 칸은 (r, c)둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. r은 ν–‰, cλŠ” 열이고, (R, C)λŠ” μ•„λž˜ κ·Έλ¦Όμ—μ„œ κ°€μž₯ 였λ₯Έμͺ½ μ•„λž˜μ— μžˆλŠ” 칸이닀. μΉΈμ—λŠ” 상어가 μ΅œλŒ€ ν•œ 마리 λ“€μ–΄μžˆμ„ 수 μžˆλ‹€. μƒμ–΄λŠ” 크기와 속도λ₯Ό κ°€μ§€κ³  μžˆλ‹€.

λ‚šμ‹œμ™•μ€ μ²˜μŒμ— 1번 μ—΄μ˜ ν•œ μΉΈ μ™Όμͺ½μ— μžˆλ‹€. λ‹€μŒμ€ 1초 λ™μ•ˆ μΌμ–΄λ‚˜λŠ” 일이며, μ•„λž˜ 적힌 μˆœμ„œλŒ€λ‘œ μΌμ–΄λ‚œλ‹€. λ‚šμ‹œμ™•μ€ κ°€μž₯ 였λ₯Έμͺ½ μ—΄μ˜ 였λ₯Έμͺ½ 칸에 μ΄λ™ν•˜λ©΄ μ΄λ™μ„ λ©ˆμΆ˜λ‹€.

  1. λ‚šμ‹œμ™•μ΄ 였λ₯Έμͺ½μœΌλ‘œ ν•œ μΉΈ μ΄λ™ν•œλ‹€.
  2. λ‚šμ‹œμ™•μ΄ μžˆλŠ” 열에 μžˆλŠ” 상어 μ€‘μ—μ„œ λ•…κ³Ό 제일 κ°€κΉŒμš΄ 상어λ₯Ό μž‘λŠ”λ‹€. 상어λ₯Ό 작으면 κ²©μžνŒμ—μ„œ μž‘μ€ 상어가 사라진닀.
  3. 상어가 μ΄λ™ν•œλ‹€.

μƒμ–΄λŠ” μž…λ ₯으둜 μ£Όμ–΄μ§„ μ†λ„λ‘œ μ΄λ™ν•˜κ³ , μ†λ„μ˜ λ‹¨μœ„λŠ” μΉΈ/μ΄ˆμ΄λ‹€. 상어가 μ΄λ™ν•˜λ €κ³  ν•˜λŠ” 칸이 격자판의 경계λ₯Ό λ„˜λŠ” κ²½μš°μ—λŠ” λ°©ν–₯을 λ°˜λŒ€λ‘œ λ°”κΏ”μ„œ 속λ ₯을 μœ μ§€ν•œμ±„λ‘œ μ΄λ™ν•œλ‹€.

μ™Όμͺ½ 그림의 μƒνƒœμ—μ„œ 1μ΄ˆκ°€ μ§€λ‚˜λ©΄ 였λ₯Έμͺ½ μƒνƒœκ°€ λœλ‹€. 상어가 보고 μžˆλŠ” λ°©ν–₯이 μ†λ„μ˜ λ°©ν–₯, μ™Όμͺ½ μ•„λž˜μ— 적힌 μ •μˆ˜λŠ” 속λ ₯이닀. μ™Όμͺ½ μœ„μ— 상어λ₯Ό κ΅¬λΆ„ν•˜κΈ° μœ„ν•΄ 문자λ₯Ό μ μ—ˆλ‹€.

상어가 이동을 마친 후에 ν•œ 칸에 상어가 두 마리 이상 μžˆμ„ 수 μžˆλ‹€. μ΄λ•ŒλŠ” 크기가 κ°€μž₯ 큰 상어가 λ‚˜λ¨Έμ§€ 상어λ₯Ό λͺ¨λ‘ μž‘μ•„λ¨ΉλŠ”λ‹€.

λ‚šμ‹œμ™•μ΄ 상어 λ‚šμ‹œλ₯Ό ν•˜λŠ” 격자판의 μƒνƒœκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, λ‚šμ‹œμ™•μ΄ μž‘μ€ μƒμ–΄ 크기의 합을 κ΅¬ν•΄λ³΄μž.

μž…λ ₯

첫째 쀄에 격자판의 크기 R, C와 μƒμ–΄μ˜ 수 M이 μ£Όμ–΄μ§„λ‹€. (2 ≤ R, C ≤ 100, 0 ≤ M ≤ R×C)

λ‘˜μ§Έ 쀄뢀터 M개의 쀄에 μƒμ–΄μ˜ 정보가 μ£Όμ–΄μ§„λ‹€. μƒμ–΄μ˜ μ •λ³΄λŠ” λ‹€μ„― μ •μˆ˜ r, c, s, d, z (1 ≤ r ≤ R, 1 ≤ c ≤ C, 0 ≤ s ≤ 1000, 1 ≤ d ≤ 4, 1 ≤ z ≤ 10000) λ‘œ 이루어져 μžˆλ‹€. (r, c)λŠ” μƒμ–΄μ˜ μœ„μΉ˜, sλŠ” 속λ ₯, dλŠ” 이동 λ°©ν–₯, zλŠ” 크기이닀. dκ°€ 1인 κ²½μš°λŠ” μœ„, 2인 κ²½μš°λŠ” μ•„λž˜, 3인 κ²½μš°λŠ” 였λ₯Έμͺ½, 4인 κ²½μš°λŠ” μ™Όμͺ½μ„ μ˜λ―Έν•œλ‹€.

두 상어가 같은 크기λ₯Ό κ°–λŠ” κ²½μš°λŠ” μ—†κ³ , ν•˜λ‚˜μ˜ 칸에 λ‘˜ μ΄μƒμ˜ 상어가 μžˆλŠ” κ²½μš°λŠ” μ—†λ‹€.

좜λ ₯

λ‚šμ‹œμ™•μ΄ μž‘μ€ 상어 크기의 합을 좜λ ₯ν•œλ‹€.

예제 μž…λ ₯ 1 λ³΅μ‚¬

4 6 8
4 1 3 3 8
1 3 5 2 9
2 4 8 4 1
4 5 0 1 4
3 3 1 2 7
1 5 8 4 3
3 6 2 1 2
2 2 2 3 5

예제 좜λ ₯ 1 λ³΅μ‚¬

22

각 칸의 μ™Όμͺ½ μ•„λž˜μ— 적힌 μˆ˜λŠ” 속λ ₯, 였λ₯Έμͺ½ μ•„λž˜λŠ” 크기, μ™Όμͺ½ μœ„λŠ” 상어λ₯Ό κ΅¬λΆ„ν•˜κΈ° μœ„ν•œ λ¬Έμžμ΄λ‹€. 였λ₯Έμͺ½ μœ„μ— β€οΈλŠ” λ‚šμ‹œμ™•μ΄ μž‘μ€ λ¬Όκ³ κΈ° ν‘œμ‹œμ΄λ‹€.

초기 μƒνƒœ

1초

2초 (E번 μƒμ–΄λŠ” Bλ²ˆμ—κ²Œ λ¨Ήν˜”λ‹€)

3초

4초

5초

6초

전체 μ½”λ“œ

import java.util.*;
import java.io.*;

class Shark{
	public int r, c, s, d, z;
	public 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;
	}
}

public class Main {
	static int R;
	static int C;
	static int M;
	static int result;
	static List<Shark> s;
	static int king;
	static Shark[][] sea;
	static int[] dx = {0, -1, 1, 0, 0};
	static int[] dy = {0, 0, 0, 1, -1}; // μž…λ ₯ 인덱슀λ₯Ό λ§žμΆ”λ €κ³ 
	
    public static void main(String[] args) throws Exception {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st = new StringTokenizer(bf.readLine(), " ");
        
        R = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());
        sea = new Shark[R][C];
        
        int T = Integer.parseInt(st.nextToken());
        s = new ArrayList<>();
        for(int i=0; i<T; i++) {
        	st = new StringTokenizer(bf.readLine(), " ");
        	int r = Integer.parseInt(st.nextToken()) -1;
        	int c = Integer.parseInt(st.nextToken()) -1;
        	Shark sk = new Shark(r, c, Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
        	s.add(sk);
        	sea[r][c] = sk;
        }
        while(king < C) {
        	move_shark();
        }
        sb.append(result);
        System.out.println(sb.toString());
        
    }
    static void move_shark() {
    	
    	// λ‚šμ‹œμ™•μ˜ 이동 & 상어 사라짐
    	for(int i=0; i<R; i++) {
    		if(sea[i][king] != null) {
    			Shark sk = sea[i][king];
    			result += sk.z;
    			s.remove(sk);
    			sea[i][king] = null;
    			break;
    		}
    	}
    	// μƒμ–΄μ˜ 이동
    	int nx, ny;
    	int size = s.size();
    	for(int i = size-1; i>=0; i--) {
    		Shark sk = s.get(i);
    		if(sea[sk.r][sk.c] == sk)
    			sea[sk.r][sk.c] = null;
    		for(int k=0; k<sk.s; k++) {
    			nx = sk.r + dx[sk.d];
    			ny = sk.c + dy[sk.d];
    			if(nx < 0 || ny < 0 || nx >= R || ny >= C) {
    				if(sk.d % 2 == 0) sk.d -= 1;
    				else sk.d += 1;
    				nx = sk.r + dx[sk.d];
        			ny = sk.c + dy[sk.d];
    			}
    			sk.r = nx; sk.c = ny;
    		}
    		if(sea[sk.r][sk.c] != null && s.indexOf(sea[sk.r][sk.c]) > i) {
    			if(sea[sk.r][sk.c].z > sk.z) {
    				s.remove(i);
    			}
    			else {s.remove(sea[sk.r][sk.c]); sea[sk.r][sk.c] = sk;}
    		}
    		else {sea[sk.r][sk.c] = sk;}
    		
    	}
    	king ++;
    }
}

ν•œ 쀄 μ”© μ‚΄νŽ΄λ³΄μž!

class Shark{
	public int r, c, s, d, z;
	public 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;
	}
}

상어 클래슀λ₯Ό μ„ μ–Έν•œλ‹€.

ν–‰, μ—΄μ˜ μœ„μΉ˜μ™€ 속λ ₯, 이동 λ°©ν–₯, 크기 정보λ₯Ό λ°›μ•„μ„œ 객체에 μ €μž₯ν•  것이닀.

static int R;
static int C;
static int M;
static int result;
static List<Shark> s;
static int king;
static Shark[][] sea;
static int[] dx = {0, -1, 1, 0, 0};
static int[] dy = {0, 0, 0, 1, -1};

μž…λ ₯받은 λ°°μ—΄μ˜ 크기λ₯Ό R, C에 μ €μž₯ν•œλ‹€. μƒμ–΄μ˜ μˆ˜λŠ” M에 μ €μž₯ν•΄μ€€λ‹€. result에 μž‘μ€ 상어 크기의 합을 μ €μž₯ν•  것이닀. sλ₯Ό 톡해 상어 객체 리슀트λ₯Ό λ§Œλ“€μ–΄μ€€λ‹€.

λ‚™μ‹œμ™•μ˜ μœ„μΉ˜ 열은 king λ³€μˆ˜μ— μ €μž₯ν•΄μ€€λ‹€.

sea 배열을 톡해 각 μœ„μΉ˜μ— μžˆλŠ” 상어λ₯Ό μ €μž₯ν•΄μ€€λ‹€.

μƒμ–΄λŠ” 총 4κ°€μ§€μ˜ 이동방ν–₯을 κ°–λŠ”λ° μ΄λ•Œ 1~4둜 μž…λ ₯이 λ“€μ–΄μ˜€κΈ° λ•Œλ¬Έμ— 배열을 1~4둜 λ°”λ‘œ μ‚¬μš©ν•  수 있게 μˆœμ„œμ™€ 인덱슀λ₯Ό λ§žμΆ”μ–΄μ£Όμ—ˆλ‹€.

R = Integer.parseInt(st.nextToken());
C = Integer.parseInt(st.nextToken());
sea = new Shark[R][C];

int T = Integer.parseInt(st.nextToken());
s = new ArrayList<>();
for(int i=0; i<T; i++) {
	st = new StringTokenizer(bf.readLine(), " ");
	int r = Integer.parseInt(st.nextToken()) -1;
	int c = Integer.parseInt(st.nextToken()) -1;
	Shark sk = new Shark(r, c, Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
	s.add(sk);
	sea[r][c] = sk;
}
while(king < C) {
	move_shark();
}
sb.append(result);
System.out.println(sb.toString());

R, C에 값을 μž…λ ₯ λ°›λŠ”λ‹€. sea[r][c] μœ„μΉ˜μ— 상어가 μ‘΄μž¬ν•˜λ©΄ κ·Έ 객체λ₯Ό μ €μž₯ν•œλ‹€.

λ‚™μ‹œμ™•μ€ μ—΄ μœ„λ₯Ό μ΄λ™ν•˜λ©° 움직이고 격자λ₯Ό λ²—μ–΄λ‚˜λ©΄ 더 이상 λ‚šμ‹œλ₯Ό ν•  수 μ—†κΈ° λ•Œλ¬Έμ— λ‚™μ‹œμ™•μ΄ C보닀 μž‘μ„ λ•ŒκΉŒμ§€λ§Œ λ‚šμ‹œλ₯Ό μ§„ν–‰ν•œλ‹€.

static void move_shark() {
	// λ‚šμ‹œμ™•μ˜ 이동 & 상어 사라짐
	for(int i=0; i<R; i++) {
		if(sea[i][king] != null) {
			Shark sk = sea[i][king];
			result += sk.z;
			s.remove(sk);
			sea[i][king] = null;
			break;
		}
	}

λ‚™μ‹œμ™•μ€ ν˜„μž¬ μœ„μΉ˜ν•œ μ—΄μ˜ κ°€μž₯ κ°€κΉŒμš΄ ν–‰(즉, 0에 κ°€μž₯ κ°€κΉŒμš΄ 행을 κ°€μ§€λŠ” κ³³)의 상어λ₯Ό μž‘λŠ”λ‹€. 행을 μ¦κ°€μ‹œν‚€λ©° κ·Έ μœ„μΉ˜μ— 상어가 μ‘΄μž¬ν•˜λ©΄(null이 μ•„λ‹ˆλ©΄) 상어λ₯Ό 이차원 λ°°μ—΄κ³Ό listμ—μ„œ μ œκ±°ν•˜κ³  μƒμ–΄μ˜ 크기λ₯Ό 더해쀀닀.

μ œκ±°ν•˜λ©΄μ„œ μ΄ˆκΈ°ν™”λ₯Ό ν•΄μ£ΌλŠ” 것을 μžŠμ§€ 말자

int nx, ny;
int size = s.size();
for(int i = size-1; i>=0; i--) {
	Shark sk = s.get(i);
	if(sea[sk.r][sk.c] == sk)
		sea[sk.r][sk.c] = null;
	for(int k=0; k<sk.s; k++) {
		nx = sk.r + dx[sk.d];
		ny = sk.c + dy[sk.d];
		if(nx < 0 || ny < 0 || nx >= R || ny >= C) {
			if(sk.d % 2 == 0) sk.d -= 1;
			else sk.d += 1;
			nx = sk.r + dx[sk.d];
  			ny = sk.c + dy[sk.d];
		}
		sk.r = nx; sk.c = ny;
	}

상어λ₯Ό μ‚­μ œν•˜λŠ” 과정이 있기 λ•Œλ¬Έμ— 인덱슀λ₯Ό λ’€μ—μ„œλΆ€ν„° 쑰사해쀀닀. λ˜ν•œ list의 크기가 가변적이기 λ•Œλ¬Έμ— λ³€μˆ˜μ— 값을 μ €μž₯ν•˜μ—¬ λŒ€μ²΄ν•œλ‹€.

상어 객체λ₯Ό λ°›μ•„ 이차원 λ°°μ—΄μ—μ„œ 상어 객체λ₯Ό μ œκ±°ν•˜κ³  λ‹€μŒ 이동 μœ„μΉ˜λ₯Ό μ‘°μ‚¬ν•˜μ—¬ λ„˜μ–΄κ°€λŠ” 경우 λ°©ν–₯을 λ°”κΏ”κ°€λ©΄μ„œ λ‹€μŒ μœ„μΉ˜λ₯Ό μ§€μ •ν•œλ‹€.

if(sea[sk.r][sk.c] != null && s.indexOf(sea[sk.r][sk.c]) > i) {
  			if(sea[sk.r][sk.c].z > sk.z) {
  				s.remove(i);
  			}
  			else {s.remove(sea[sk.r][sk.c]); sea[sk.r][sk.c] = sk;}
  		}
  		else {sea[sk.r][sk.c] = sk;}
  		
  	}
  	king ++;
  }
}

이동할 μœ„μΉ˜κ°€ κ²°μ •λœ 경우 κ·Έ μœ„μΉ˜μ— λ‹€λ₯Έ 상어가 μ‘΄μž¬ν•˜λ©΄ & 그리고 κ·Έ 상어가 이번 μ‹œκ°„μ— μ΄λ™ν•œ 것이라면? (인덱슀λ₯Ό 거꾸둜 μ΄λ™ν•˜κ³  있기 λ•Œλ¬Έμ— 더 큰 인덱슀λ₯Ό κ°€μ§„ μƒμ–΄λŠ” λ¨Όμ € μ΄λ™ν•˜λŠ” κ²ƒμœΌλ‘œ 체크 κ°€λŠ₯ν•˜λ‹€.)

그런 경우 크기가 μž‘μ€ 상어λ₯Ό μ œκ±°ν•œλ‹€.

κ·Έ λ’€ λ‚™μ‹œμ™•μ˜ μœ„μΉ˜λ₯Ό 이동해쀀닀.