본문 바로가기

알고리즘/코드트리

나무박멸[G4]

목차

    https://csg1353.tistory.com/51

     

    이전에 틀렸던 문제를 연습차 다시 풀이하였다.

     

    코드

    import java.util.*;
    import java.io.*;
    
    public class Main {
           static int N, M, K, C;
       static int[][] map;
       static int[][] jecho;
       static int answer;
       static Queue<Pos> tempQ = new ArrayDeque<>();
       static Queue<Pos> treeQ = new ArrayDeque<>();
       static final int[] DR = {-1, 0, 1, 0};
       static final int[] DC = {0, 1, 0, -1};
       static final int[] DCR = {-1, -1, 1, 1}; //좌상 / 우상 / 좌하 / 우하
       static final int[] DCC = {-1, 1, -1, 1}; //대각선 살포용
    
        public static void main(String[] args) throws Exception {
                  input();
          while(M-- > 0) {
             grow();
             spread();
             Pos result = target();
             remove(result); //제초제 살포
             minus(); //제초제 1년 감소
          }
          System.out.println(answer);
        }
    
         public static void grow() {
          for(int r = 0; r < N; r++) {
             for(int c = 0; c < N; c++) {
                if(map[r][c] <= 0) continue; 
                int cnt = 0;
                for(int k = 0; k < 4; k++) {
                   int nr = r + DR[k];
                   int nc = c + DC[k];
                   if(cantGo(nr, nc)) continue;
                   if(map[nr][nc] > 0) cnt++;
                }
                map[r][c] += cnt; //자기자신 성장
             }
          }
       }
       
       public static void spread() {
          //인접한 4칸 번식, 제초제가 있는지 맵밖인지 벽인지 확인
          for(int r = 0; r < N; r++) {
             for(int c = 0; c < N; c++) {
                if(map[r][c] <= 0) continue;
                int cnt = 0; //인접칸
                for(int k = 0; k < 4; k++) {
                   int nr = r + DR[k];
                   int nc = c + DC[k];
                   if(cantGo(nr, nc) || map[nr][nc] != 0 || jecho[nr][nc] > 0) continue;
                   cnt++;
                   tempQ.add(new Pos(nr, nc));
                }
                
                while(!tempQ.isEmpty()) {
                   Pos now = tempQ.poll();
                   now.value = map[r][c] / cnt;
                   treeQ.add(now);
                }
             }
          }
          
          //번식
          while(!treeQ.isEmpty()) {
             Pos now = treeQ.poll();
             map[now.r][now.c] += now.value;
          }
       }
       
       public static Pos target() {
          Pos result = new Pos(0, 0, 0); //제초제 스팟
          for(int r = 0; r < N; r++) {
             for(int c = 0; c < N; c++) {
                checkTarget(r, c, result); //각 스팟 별 체크
             }
          }
          
          return result;
       }
       
      public static void checkTarget(int r, int c, Pos result) {
          //r c에서 대각선으로 K칸까지 박멸 발생
          int res = Math.max(map[r][c], 0); //0 이상 현재 위치 값 기본
          int nr, nc;
          if(map[r][c] <= 0) return;
          
    	  for(int j = 0; j < 4; j++) {
              for(int i = 1; i <= K; i++) {
                 nr = r + (DCR[j] * i); 
                 nc = c + (DCC[j] * i);
                 if(cantGo(nr, nc)) break;
                 res += Math.max(map[nr][nc], 0);
                 if(map[nr][nc] <= 0 || jecho[nr][nc] > 0) break;
              }
    	  }
    
    //	  System.out.println(r + " " + c + " " + res);
          if(res > result.value || 
                (res == result.value && r < result.r) || //결과가 같은데 행이 작음 
                (res == result.value && r == result.r && c < result.c)) {  //결과 및 행 같으면 열 작음
             result.r = r;
             result.c = c;
             result.value = res;
    
          }
       }
    
       static void remove(Pos result) {
          int nr, nc;
          int r = result.r; int c = result.c;
          //r c부터 제초제 살포 시작
          tempQ.add(new Pos(r, c, C + 1)); //jecho
          
    
    	  for(int j = 0; j < 4; j++) {
              for(int i = 1; i <= K; i++) {
                 nr = r + (DCR[j] * i); 
                 nc = c + (DCC[j] * i); 
                 if(cantGo(nr, nc)) break;
               	 tempQ.add(new Pos(nr, nc, C + 1)); //jecho
               	if(map[nr][nc] <= 0 || jecho[nr][nc] > 0) break;
                  }
    	  }
       
          
          while(!tempQ.isEmpty()) {
        	  Pos now = tempQ.poll();
        	  jecho[now.r][now.c] = now.value;
    //    	  System.out.println(now.r + " " + now.c);
          }
          
       }
       
       static void minus() {
          for(int i = 0; i < N; i++) {
             for(int j = 0; j < N; j++) {
                if(jecho[i][j] > 0) {
                	jecho[i][j] -= 1;
                    if(map[i][j] > 0) { //나무 있을 경우
                    	answer += map[i][j];
                    	map[i][j] = 0; //제초제
                    }
                }
             }
          }
       }
       
       static boolean cantGo(int r, int c) {
          if(r < 0 || c < 0 || r >= N || c >= N) return true;
          return false;
       }
       public static void input() throws Exception {
          BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
          StringTokenizer st = new StringTokenizer(br.readLine());
          N = Integer.parseInt(st.nextToken());
          M = Integer.parseInt(st.nextToken());
          K = Integer.parseInt(st.nextToken());
          C = Integer.parseInt(st.nextToken());
          map = new int[N][N];
          jecho = new int[N][N];
          for(int i = 0; i < N; i++) {
             st = new StringTokenizer(br.readLine());
             for(int j = 0; j < N; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
             }
          }
       }
    }
    
    class Pos {
       int r, c, value;
       public Pos(int r, int c, int value) {
          this.r = r;
          this.c = c;
          this.value = value;
       }
       
       public Pos(int r, int c) {
          this.r = r;
          this.c = c;
       }
    }

    '알고리즘 > 코드트리' 카테고리의 다른 글

    왕실의 기사 대결[G3]  (0) 2024.04.11
    루돌프의 반란[G2]  (0) 2024.04.09
    원자 충돌[G4]  (0) 2023.11.02
    놀이기구 탑승[G5]  (0) 2023.11.02
    팩맨[G1]  (1) 2023.11.02