[java]나무 재테크 - 백준16235

문제



풀이

문제 해석을 하자면,

  • K년이 지난 후 상도의 땅에 살아있는 나무의 개수를 구해야 하는 문제
  • 단, 조건이 많고 시간초과도 조심해야하는 까다로운 문제이다.


풀이

  • 입력좌표 (0,0) 으로 사용할거라 -1 임의로 추가했음
  • 가장 처음에 양분은 모든 칸에 5만큼 들어있다는점 놓지지 말자
  • “시간초과 해결방법” -> 주석 확인
    • 우선순위 큐 오버라이딩을 직접하는게 더 빠름(중요)
    • !qu.isEmpty() 보다 size 미리 구해서 사용하는게 더 빠름
    • 큐는 copyQu 만 계속 새로 할당하고, 2개의 큐를 번갈아가면서 낭비없이 사용(중요)
    • 문제에 적용은 안했는데 “큐” 사용할때 LinkedList 보다 ArrayDeque가 더 빠름



코드

public static int N, M, K;
	public static int[][] inMap = new int[12][12];
	public static int[][] foodMap = new int[12][12]; // 입력 양분
	public static PriorityQueue<Tree> qu = new PriorityQueue<>();
	public static PriorityQueue<Tree> copyQu;
	public static Queue<Tree> dieQu = new LinkedList<>(); // 죽은나무 기록
	public static int[] dx = {-1,-1,-1,0,0,1,1,1};
	public static int[] dy = {-1,0,1,-1,1,-1,0,1};
	// (r-1, c-1), (r-1, c), (r-1, c+1), (r, c-1), (r, c+1), (r+1, c-1), (r+1, c), (r+1, c+1)
			
	public static void spring() {
//		copyQu = new PriorityQueue<>(Tree::compareTo); // 매번 새로 할당
		copyQu = new PriorityQueue<>(); // 매번 새로 할당
		int size = qu.size(); // !isEmpty 보다 더 빠른것 같음
		while(size-- > 0) {
			Tree t = qu.peek();
			qu.remove();
			int food = inMap[t.x][t.y];
			if(food < t.age) {
				dieQu.add(t);
				continue; // 못먹으면 사망
			}
			inMap[t.x][t.y]-=t.age;
			t.age+=1; // 먹으면 나이++
			copyQu.add(t);
		}
	}
	
	public static void summer() {
		int size = dieQu.size();
		while(size-- > 0) {
			Tree t= dieQu.peek();
			dieQu.remove();
			inMap[t.x][t.y]+=t.age/2; 
		}
	}
	
	public static void fall() {
		int size = copyQu.size();
		while(size-- > 0) {
			Tree t = copyQu.peek();
			copyQu.remove();
			if(t.age % 5 ==0) {
				// 번식
				for(int i=0; i<8; i++) {
					int nx = t.x+dx[i];
					int ny = t.y+dy[i];
					if(nx<0||ny<0||nx>=N||ny>=N) continue;
					qu.add(new Tree(nx, ny, 1)); // 번식나무 생성
				}
			}
			qu.add(t);
		}
	}
	
	public static void winter() {
		for(int i=0; i<N; i++) {
			for(int j=0; j<N; j++) {
				inMap[i][j] += foodMap[i][j];
			}
		}
	}
	
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer stk = new StringTokenizer(br.readLine(), " ");
		N = Integer.parseInt(stk.nextToken());
		M = Integer.parseInt(stk.nextToken());
		K = Integer.parseInt(stk.nextToken());
		for(int i=0; i<N; i++) {
			stk = new StringTokenizer(br.readLine(), " ");
			for(int j=0; j<N; j++) {
				inMap[i][j] = 5; // 초기값
				foodMap[i][j] = Integer.parseInt(stk.nextToken());
			}
		}
		for(int i=0; i<M; i++) {
			stk = new StringTokenizer(br.readLine(), " ");
			int x = Integer.parseInt(stk.nextToken())-1; // 좌표 0,0 으로 사용할거라 -1
			int y = Integer.parseInt(stk.nextToken())-1;
			int age = Integer.parseInt(stk.nextToken());
			qu.add(new Tree(x,y,age));
		}
		//run
		for(int i=0; i<K; i++) {
			//1.봄
			spring();
			//2.여름
			summer();
			//3.가을
			fall();
			//4.겨울	
			winter();
		}
		//output
		System.out.println(qu.size());
		
	}

//	static class Tree {
//		int x; int y; int age;
//		public Tree(int x, int y, int age) {
//			this.x=x; this.y=y; this.age=age;
//		}
//		
//		public int compareTo(Tree t) {
//			if(this.age < t.age) {
//				return -1;
//			}
//			return 1;
//		}
//	}
	
	static class Tree implements Comparable<Tree> {
	    int x, y, age;
	    
	    Tree(int x, int y, int age) {
	        this.x = x;
	        this.y = y;
	        this.age = age;
	    }
	    
	    public int compareTo(Tree t) {
	    	return Integer.compare(this.age, t.age);
	    }
	}



느낀점

생략

댓글남기기