PS/BOJ
2112 보호필름
easy16
2022. 5. 14. 13:32
전략
1. 약품처리 K를 사용하는 경우의 수를 중복순열을 사용하여 3가지로 정의함.
(-1 : 아무것도 하지 않음)
( 0 : A 약품)
( 1 : B 약품)
2. check 함수를 어떤식으로 구현할까 고민했지만, 탐색을 위한 특별한 전략이 없다고 판단 BF로 진행.
문제 조건을 살펴보면, worst cast의 실행횟수는
3^13 * D*W = 3 ^ 13 × 13 × 20 = 414,523,980
정도이며 실행시간이 5초 이내임을 감안하면 충분하다 판단함.
3. check 구현시, map을 직접 수정하면 원래대로 되돌리는 것이 번거롭기 때문에 dummy를 생성하여 사용후 버림.
완성 후 다음 사이트와 비교하여, 구현상의 차이점 정도를 살펴보면 좋을듯 싶다.
https://velog.io/@hyeon930/SWEA-2112-%EB%B3%B4%ED%98%B8-%ED%95%84%EB%A6%84-Java
import java.util.Arrays;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStreamReader;
class Solution {
static int D, W, K;
static int[][] skin, dummy;
private static boolean DBG = false;
static int min;
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();
for (int test_case = 1; test_case <= T; test_case++) {
st = new StringTokenizer(br.readLine());
D = Integer.parseInt(st.nextToken());
W = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
skin = new int[D][W];
dummy = new int[D][W];
for (int i = 0; i < D; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < W; j++) {
skin[i][j] = Integer.parseInt(st.nextToken());
}
}
// index, cnt
// 중복 순열
min=Integer.MAX_VALUE;
go(0, 0, new int[D]);
System.out.println("#" + test_case + " " +min);
}
System.out.println(sb);
}
private static void go(int level, int cnt, int[] perm) {
if (level == D) {
if (cnt > K) {
return;
}
StringBuilder sb = new StringBuilder();
if (DBG) {
sb.append("perm : \n");
for (int v : perm)
sb.append(v).append(' ');
// System.out.println(sb);
sb.append('\n');
}
// i, perm[i] => map's row , value
int ii = 0;
for (int[] ar : skin)
dummy[ii++] = Arrays.copyOf(ar, ar.length);
for (int i = 0; i < perm.length; i++) {
int value = perm[i];
if (value == -1)
continue;
Arrays.fill(dummy[i], value);
}
if (DBG) {
sb.append("dummy : \n");
for (int[] ar : dummy) {
for (int v : ar) {
sb.append(v).append(' ');
}
sb.append('\n');
}
System.out.println(sb);
}
if (check() == true) {
//System.out.println("pass!");
min = Math.min(min, cnt);
} else {
//System.out.println("NG!");
}
return;
}
// 중복 순열
for (int i = -1; i < 2; i++) {
perm[level] = i;
cnt = (i == -1) ? cnt : cnt + 1;
go(level + 1, cnt, perm);
cnt = (i == -1) ? cnt : cnt - 1;
}
}
private static boolean check() {
boolean result = true;
for ( int i = 0 ; i < W ; i++) {
int cnt = 1;
for (int j = 1 ; j < D ; j++) {
if( dummy[j-1][i] == dummy[j][i])
cnt++;
else
cnt = 1;
if (cnt >= K) break;
}
if( cnt < K)
return false;
}
return result;
}
}