PS/BOJ
2383 점심 식사시간
easy16
2022. 5. 15. 12:15
이번 문제는 해결법을 생각해내지 못했다.
머리속에 Q를 사용하여 각 P를 처리해야될 것 같다까지는 떠올랐지만 실패했다.
이후 구현 방법에 대한 구체가 없어서 검색을 통해 아래의 해결 방법 및 코드를 학습했다.
전략
1. 계단이 총2개 존재하므로, 각 계단에 대해 Q를 할당한다.
2. P의 숫자나 맵의 크기가 시간초과가 발생할 정도로 크지 않기 때문에 완전탐색(DFS)을 통해 P가 계단을 선택하는 모든 경우의 수를 시뮬레이션한다. ( 이부분을 전혀 생각해내지 못함, 이 부분만 떠올랐으면 풀어 냈을지도 )
3. 각 case에 대한 simulation을 진행한다.
도착시간이 지나고 Q에 빈자리가 생기면 enqueue해준다.
다음 iteration에서 , 계단을 내려가고 있는 P에 대한 처리를 진행한다.
계단에 진입한 이후 k시간이 지나면 Q에서 제거, 그렇지 않다면 다시 enqueue해준다.
모든 P가 계단에 진입하고(cnt), q1/q2가 empty이면 모든 상황이 종료된다.
유사한 문제가 나왔을 때 활용할 수 있도록 아래의 코드형태를 잘 기억하는게 좋을것 같다.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
class P {
int x, y;
int arrivalTime;// 계단 도착시간
int stair;// 계단 종류
int stairTime;// 계단을 내려가기 시작한 시각
P(int x, int y) {
this.x = x;
this.y = y;
}
public void setArrivalTime(S s) {
arrivalTime = Math.abs(x - s.x) + Math.abs(y - s.y);
}
}
class S {
int x, y, k, cnt;
S(int x, int y, int k) {
this.x = x;
this.y = y;
this.k = k;
}
}
class Solution {
static int N;
static int[][] map;
static ArrayList<P> pList;
static ArrayList<S> sList;
static boolean[] visited;
static Queue<P>[] Q;
private static int ans;
public static void main(String args[]) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T;
T = Integer.parseInt(br.readLine());
StringTokenizer st = null;
StringBuilder sb = new StringBuilder();
long startTime = System.currentTimeMillis();
for (int test_case = 1; test_case <= T; test_case++) {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
pList = new ArrayList<>();
sList = new ArrayList<>();
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
int v = Integer.parseInt(st.nextToken());
if (v == 1) {
pList.add(new P(i, j));
} else if (v != 0) {
sList.add(new S(i, j, v));
}
}
}
// init
ans = Integer.MAX_VALUE;
Q = new LinkedList[2];
Q[0] = new LinkedList<>();
Q[1] = new LinkedList<>();
go(0);
System.out.println("#" + test_case + " " + ans);
}
}
private static void go(int level) {
if (level == pList.size()) {
visited = new boolean[pList.size()];
int cur = simulation();
ans = Math.min(cur, ans);
return;
}
pList.get(level).stair = 0;
pList.get(level).setArrivalTime(sList.get(0));
go(level + 1);
pList.get(level).stair = 1;
pList.get(level).setArrivalTime(sList.get(1));
go(level + 1);
}
private static int simulation() {
int cnt = 0;
int time = 0;
while (true) {
// Q안의 P중, 도착시간 + K가 현재시간과 같아지면, 제거한다.
for (int i = 0; i < 2; i++) {
int size = Q[i].size();
for (int j = 0; j < size; j++) {
P p = Q[i].poll();
S s = sList.get(i);
if (p.stairTime + s.k <= time)
continue;
Q[i].offer(p);
}
}
if (cnt == pList.size() && Q[0].isEmpty() && Q[1].isEmpty()) {
return time;
}
// Q안에 대기가 3개 미만이면 P를 넣어준다.
for (int i = 0; i < pList.size(); i++) {
P p = pList.get(i);
Queue<P> q = Q[p.stair];
if (visited[i])
continue;
if (p.arrivalTime + 1 <= time && q.size() < 3) {
visited[i] = true;
p.stairTime = time;
q.offer(p);
cnt++;
}
}
time++;
}
}
}
참조 : https://velog.io/@hyeon930/SWEA-2383-%EC%A0%90%EC%8B%AC-%EC%8B%9D%EC%82%AC%EC%8B%9C%EA%B0%84-Java