알고리즘 공부

백준 마법사 상어와 파이어스톰

컴퓨터과학 2024. 4. 3. 00:11

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

20058번: 마법사 상어와 파이어스톰

마법사 상어는 파이어볼과 토네이도를 조합해 파이어스톰을 시전할 수 있다. 오늘은 파이어스톰을 크기가 2N × 2N인 격자로 나누어진 얼음판에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c

www.acmicpc.net

와 두번다시는 풀고 싶지는 않는문제네요
* 이후 얼음이 있는 칸 3개 또는 그 이상과 인접해있지 않은 칸은 얼음의 양이 1 줄어든다.
->3개 미만은 얼음이 줄어든다 (무슨 국어 문제인가.. ㅎ)
* 남아있는 얼음 중 가장 큰 덩어리가 차지하는 칸의 개수 얼음이 있는 칸이 얼음이 있는 칸과 인접해 있으면, 두 칸을 연결되어 있다고 한다. 덩어리는 연결된 칸의 집합
->연결된 얼음 덩어리들의 칸의 갯수의 합,즉 얼음은 bfs,dfs를 통해서 연결해서 얼음 덩어리들을 계산하라는 의미
 

import java.util.*;
import java.io.*;
import java.lang.*;
import java.io.*;
public class Main {
	public static int n;
	public static int q;
	public static int maps[][];
	public static int copyMaps[][];
	public static boolean bCheck[][];
	public static boolean initbCheck[][];
	public static boolean[][] visited; 
	public static int L;
	public static void prints(int tmpMap[][]){
		System.out.println();
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				System.out.print(tmpMap[i][j]+",");
			}
			System.out.println();
		}
	}
	public static class Ice {
		public int i;
		public int j;
		public Ice(int i,int j) {
			this.i=i;
			this.j=j;
		}
	}
	public static void Rotation(int starti, int startj){
		int cnt=1;
		int rStarti=starti*L;
		int rEndi=starti*L+L;
		int rStartj=startj*L;
		int rEndj=startj*L+L;

		int rLengthI=(rStarti+rEndi)/2;
		int rLengthJ=(rStartj+rEndj)/2;

		int rCountI=(rEndi-rStarti)/2;
		int rCountJ=(rEndi-rStarti)/2;

		//1 ->2
		for(int i=rStarti;i<rLengthI;i++){
			for(int j=rStartj;j<rLengthJ;j++){
				copyMaps[i][j+ rCountJ]=maps[i][j];
			}
		}
		//2->3
		for(int i=rStarti;i<rLengthI;i++){
			for(int j=rLengthJ;j<rEndj;j++){
				copyMaps[i+rCountI][j]=maps[i][j];
			}
		}

		//3->4
		for(int i=rLengthI;i<rEndi;i++){
			for(int j=rLengthJ ;j<rEndj;j++){
				copyMaps[i][j-rCountJ]=maps[i][j];
			}
		}
		//4->1
		for(int i=rLengthI;i<rEndi;i++){
			for(int j=rStartj;j<rLengthJ;j++){

				copyMaps[i-rCountI][j]=maps[i][j];
			}
		}
		//prints(copyMaps);
		
		

	}
	
	public static void Rotations(int starti, int startj) {
	    int rStarti = starti * L;
	    int rStartj = startj * L;
	    int[][] temp = new int[L][L];

	    for (int i = 0; i < L; i++) {
	        for (int j = 0; j < L; j++) {
	            temp[j][L - 1 - i] = maps[rStarti + i][rStartj + j];
	        }
	    }

	    for (int i = 0; i < L; i++) {
	        for (int j = 0; j < L; j++) {
	        	maps[rStarti + i][rStartj + j] = temp[i][j];
	        }
	    }
	}
	public static int bfs(int x, int y) {
	    if(maps[x][y] <= 0) return 0; 
	    int count = 1;
	    Queue<Ice> queue = new LinkedList<>();
	    queue.add(new Ice(x, y));
	    visited[x][y] = true;

	    while (!queue.isEmpty()) {
	        Ice current = queue.poll();
	        int i = current.i;
	        int j = current.j;

	        int[] di = {-1, 1, 0, 0}; 
	        int[] dj = {0, 0, -1, 1}; 

	        for (int k = 0; k < 4; k++) {
	            int ni = i + di[k];
	            int nj = j + dj[k];

	            if (ni >= 0 && ni < n && nj >= 0 && nj < n && !visited[ni][nj] && maps[ni][nj] > 0) {
	                queue.add(new Ice(ni, nj));
	                visited[ni][nj] = true;
	                count++; 
	            }
	        }
	    }
	    return count;
	}
	
	public static void main(String[] args) throws Exception {
		Scanner scan = new Scanner(System.in);
		n=scan.nextInt();
		q=scan.nextInt();
		double tmpn=Math.pow(2,n);
		n=(int)tmpn;
		maps=new int[n][n];
		copyMaps=new int[n][n];
		bCheck=new boolean[n][n];
		initbCheck=new boolean[n][n];
		visited = new boolean[n][n];

		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				maps[i][j]=scan.nextInt();
				copyMaps[i][j]=maps[i][j];
			}
		}
		for(int t=0;t<q;t++){
			
			L=scan.nextInt();

			double tmpL=Math.pow(2,L);
			L=(int)tmpL;
			//2x2
			//4x4
			//8x8
			int divide=n/L;
			
			
			for(int i=0;i<divide;i++){
				for(int j=0;j<divide;j++){
					Rotations(i,j);
				}
			}
			
			int diri[]= {-1,1,0,0};
			int dirj[]= {0,0,-1,1};
			
			ArrayList<Ice> saveIce=new ArrayList<>();
			for (int i = 0; i < n; i++) {
			    for (int j = 0; j < n; j++) {
			        int iceCnt = 0; 
			        for (int k = 0; k < 4; k++) {
			            int ni = i + diri[k];
			            int nj = j + dirj[k];
			            if (ni < 0 || nj < 0 || ni >= n || nj >= n) continue;
			           
			            if (maps[ni][nj] > 0) iceCnt++;
			        }
			        if (iceCnt < 3) {
			            saveIce.add(new Ice(i, j));
			        }
			    }
			}

			// 저장된 모든 칸의 얼음을 1 줄입니다.
			for (Ice ice : saveIce) {
			    maps[ice.i][ice.j] = Math.max(0, maps[ice.i][ice.j] - 1); 
			}
			
		}
		
		int sum=0;
		int maxs=0;
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				if(maps[i][j]>=0) {
					sum+=maps[i][j];
				}
				
			}
		}
		System.out.println(sum);
		int maxSizeOfIce = 0;
for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        if (!visited[i][j] && maps[i][j] > 0) {
            maxSizeOfIce = Math.max(maxSizeOfIce, bfs(i, j));
        }
    }
}
		System.out.println(maxSizeOfIce);
		//Rotation(0,1);

	}
}