N*M의 연구소가 있다. 이 연구소의 일부 칸에 2로 표현된 바이러스가 있는데, 이 바이러스는 상하좌우로 퍼져나갈 수 있어서 벽을 세워 바이러스를 막으려고 한다.
벽은 무조건 3개 세워야하고 1로 표현한다. 아무것도 아닌 영역은 0으로 표현되는데, 벽 3개를 다 세우고 바이러스가 퍼져나갔을 때 남는 개수를 출력하면 되는 문제이다.
분명.. 푸는 방법은 그래도 생각해냈는데 오늘도 코딩하는 게 오래걸렸다... 하루에 하나 푸는 코린이 하이루..
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class BOJ_14502 {
static int M, N;
static int[][] map;
static int[][] mapClone;
static ArrayList<Point> virus = new ArrayList<>();
static int maxNum = 0;
static int[] dx = {0, 0, -1, 1};
static int[] dy = {-1, 1, 0, 0};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken()); //세로
M = Integer.parseInt(st.nextToken()); //가로
map = new int[N][M];
mapClone = new int[N][M];
for(int i=0; i<N; i++) {
st = new StringTokenizer(br.readLine());
for(int j =0; j<M; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if( map[i][j] == 2 ) {
virus.add(new Point(i, j));
}
}
}
setWall(0, 0, 0);
System.out.println(maxNum);
}
public static void setWall(int x, int y, int depth) {
if (depth == 3) {
//벽을 세운 상태를 copy 해야하기 때문에 clone 안하고 복사합니다
copyMap();
for(Point p : virus) {
dfs(p.x, p.y);
}
maxNum = Math.max(maxNum, getArea());
return;
}
for(int i= x; i < N; i++) {
for(int j=0; j<M; j++) {
if( i == x && j < y ) {
continue;
}
System.out.println(i+"," +j);
if(map[i][j] == 0) {
map[i][j] =1;
setWall(i, j+1, depth + 1);
map[i][j] =0;
}
}
}
}
public static void copyMap() {
for(int i=0; i<N; i++) {
for(int j=0; j<M; j++) {
mapClone[i][j] = map[i][j];
}
}
}
public static int getArea() {
int count =0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (mapClone[i][j] == 0) {
count++;
}
}
}
return count;
}
public static void dfs(int x, int y) {
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < N && ny >= 0 && ny < M) {
if (mapClone[nx][ny] == 0) {
mapClone[nx][ny] = 2;
dfs(nx, ny);
}
}
}
}
static class Point {
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}
가로 세로가 XY좌표 - 행렬은 다르다는거 자꾸 헷갈린다. 주의하자..
그리고 조합 부분은 하다가 모르겠어서 찾아봤다. 결국 서치해서 백트래킹을 사용했다.
백트래킹은 완전탐색을 하는 과정에서, 조건에 부합하지 않으면 다시 이전의 상태로 되돌아가 다시 서치하는 알고리즘이다.
+++ 추가
깊은 복사 : 값 자체만 복사하는 것. 한 배열을 수정해도 다른 배열에 영향을 미치지 않는다.
--> 2차원 배열의 경우 이중 for문을 순회하며 복사하는 방법이 있다.
1차원 배열은 clone()을 사용해주면 간단히 가능👌
객체 배열의 경우는 객체의 주소값을 가지고 있어서 깊은 복사가 안된다.
얕은 복사 : 객체의 주소값이 복사된다. 그래서 한 배열을 수정하면, 다른 배열도 같이 수정된다.