Skip to content

Commit

Permalink
Merge pull request #192 from sds-2021-summer-algorithm/yukyeongmin-pa…
Browse files Browse the repository at this point in the history
…tch-2

[유경민] 연구소3 (성공)
  • Loading branch information
yukyeongmin authored Nov 19, 2021
2 parents 0532089 + 60d27cf commit 3240c0d
Showing 1 changed file with 39 additions and 48 deletions.
87 changes: 39 additions & 48 deletions solution/BOJ_17142_연구소-3/ykm.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

Expand All @@ -30,22 +30,6 @@ public virus(int x, int y, boolean active, int count) {
this.count = count;
}

public boolean isActive() {
return active;
}

public void setActive(boolean active) {
this.active = active;
}

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

@Override
public int compareTo(Main.virus o) {
return this.count - o.count;
Expand All @@ -55,6 +39,7 @@ public int compareTo(Main.virus o) {
static int N; // 연구소의 크기
static int M; // 바이러스 개수
static int[][] Map; // 0: 빈칸, 1:벽, 2:바이러스(비활성), 3:바이러스(활성)
static boolean[][] isVirus;

static ArrayList<virus> v = new ArrayList<virus>();

Expand All @@ -64,16 +49,14 @@ public int compareTo(Main.virus o) {
static int area;

public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("input.txt"));
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][N];
area = N * N; // 바이러스가 갈수있는 공간의 넓이 = 연구소에서 벽을 제외한 공간의 넓이
answer = N * N;
area = N * N; // 바이러스가 갈수있는 공간의 넓이 = 연구소에서 벽과 바이러스 제외한 공간의 넓이
answer = N * N; // 걸리는 최종 시간

for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
Expand All @@ -83,11 +66,16 @@ public static void main(String[] args) throws IOException {
area--;
else if (Map[i][j] == 2) {
v.add(new virus(i, j));
area--;
}
}
}

activate(-1, 0);
if (area == 0)
answer = 0;
else
activate(-1, 0); // 바이러스가 퍼져야하는 공간이 있을때만 활성화 시키기

if (answer == N * N)
System.out.println(-1);
else
Expand All @@ -99,20 +87,17 @@ else if (Map[i][j] == 2) {
// DFS로 활성화 시킬 바이러스 고르기
public static void activate(int index, int count) {
if (count == M) { // 활성화가 끝나면 퍼뜨려봐야 함.
int turn = spread();
if (turn > 0) {
answer = Math.min(turn, answer);
}
answer = Math.min(spread(), answer);
return;

} else { // 활성화 시킬 M개의 바이러스 고르기
for (int i = index + 1; i < v.size(); i++) {
virus current = v.get(i);
current.setActive(true);
current.setCount(0);
current.active = true;
current.count = 0;
activate(i, count + 1);
current.setActive(false);
current.setCount(-1);
current.active = false;
current.count = -1;
}
}
}
Expand All @@ -121,26 +106,23 @@ public static void activate(int index, int count) {
// 가능한 경우 -> 퍼뜨리는데 걸린 시간
// BFS로 퍼뜨리기
public static int spread() {
boolean[][] isVisited = new boolean[N][N];
isVirus = new boolean[N][N];
int countVirus = 0;
int turn = 0;
Queue<virus> q = new LinkedList<virus>();
// pq는 메모리 효율이 좋지만 정렬때문에 느림

Queue<virus> q = new PriorityQueue<virus>();
for (int i = 0; i < v.size(); i++) {
for (int i = 0; i < v.size(); i++) { // 전체 바이러스중 활성화 된 바이러스만 q에 넣기
virus current = v.get(i);
if (current.isActive()) {
if (current.active) {
isVirus[current.x][current.y] = true; // 바이러스가 이미 퍼졌음을 표시
q.add(current);
}
}

int countVirus = 0;
int turn = 0;
while (!q.isEmpty()) {
virus current = q.poll();
isVisited[current.x][current.y] = true;
countVirus++;
turn = current.getCount();

if (countVirus == area)
return turn;
int t = current.count;

for (int i = 0; i < 4; i++) {
int nextX = current.x + mx[i];
Expand All @@ -151,16 +133,25 @@ public static int spread() {
continue;
// 벽으로는 바이러스가 퍼질수 없음.
// 이미 바이러스가 퍼진곳 제외
if (Map[nextX][nextY] == 1 || isVisited[nextX][nextY])
if (Map[nextX][nextY] == 1 || isVirus[nextX][nextY])
continue;

else {
isVisited[nextX][nextY] = true;
q.add(new virus(nextX, nextY, true, turn + 1));
// 비활성화 바이러스를 만난 경우
if (Map[nextX][nextY] == 2) {
isVirus[nextX][nextY] = true;
q.add(new virus(nextX, nextY, true, t + 1));
} else if (Map[nextX][nextY] == 0) {
isVirus[nextX][nextY] = true;
countVirus++;
q.add(new virus(nextX, nextY, true, t + 1));
turn = Math.max(turn, t + 1);
}
}

}
return 0;

if (countVirus == area)
return turn;
else
return N * N;
}
}

0 comments on commit 3240c0d

Please sign in to comment.