> 문제
2020 카카오 블라인드 채용 문제 문제 : [자물쇠와 열쇠]
> 풀이
좌물쇠의 크기를 열쇠가 최소 한블럭이 걸칠 수 있도록 구현하였다.
전체 맵의 크기는 N + (M-1)*2
(0,0) 부터 (맵크기 - M + 1, 맵크기 - M + 1) 까지 키를 90도씩 돌려놓고 탐색하였다.
그리고, 위의 전체 맵에서 좌물쇠 범위(위 배열에서 1로 되어있는 부분)만 체크하였다.
소스는 다음과 같다.
package level3;
public class Solution_자물쇠와열쇠 {
public static void main(String[] args) {
int[][] key = {{0,0,0},{1,0,0},{0,1,1}};
int[][] lock = {{1,1,1},{1,1,0},{1,0,1}};
System.out.println(solution(key, lock));
}
// 키 회전을 위한 메소드
static int[][] rotation(int[][] lock, int degree) {
if(degree == 0) return lock;
int N = lock.length;
int[][] newLock = new int[N][N];
for(int i=0; i<N; i++) {
for(int j=0; j<N; j++) {
switch(degree) {
case 90:
newLock[i][j] = lock[N-1-j][i];
break;
case 180:
newLock[i][j] = lock[N-1-i][N-1-j];
break;
case 270:
newLock[i][j] = lock[j][N-1-i];
break;
}
}
}
return newLock;
}
static public boolean solution(int[][] key, int[][] lock) {
int M = key.length;
int N = lock.length;
int[][] map = new int[N+((M-1)*2)][N+((M-1)*2)];
for(int i=M-1, a=0; a<N; i++, a++) {
for(int j=M-1, b=0; b<N; j++, b++) {
if(lock[a][b] == 1) map[i][j] = 1;
}
}
int[] degrees = {0, 90, 180, 270};
for (int r = 0; r < 4; r++) {
int[][] tmp = rotation(key, degrees[r]);
for (int i = 0; i <= map.length - M; i++) {
for (int j = 0; j <= map[i].length - M; j++) {
if (check(map, tmp, i, j)) return true;
}
}
}
return false;
}
static boolean check(int[][] map, int[][] key, int x, int y) {
boolean flag = true;
int M = key.length;
int N = map.length-((M-1)*2);
// 전체 맵 부분 키 작업 해주고,
for(int a=0; a<M; a++) {
for(int b=0; b<M; b++) {
map[a+x][b+y] += key[a][b];
}
}
// 해당 좌물쇠 범위를 체크하고, 열수없다면 false 체크하고 멈춘다.
label: for(int i=M-1, a=0; a<N; i++, a++) {
for(int j=M-1, b=0; b<N; j++, b++) {
if(map[i][j] != 1) {
flag = false;
break label;
}
}
}
// 키 작업했던 부분 초기화.
for(int a=0; a<M; a++) {
for(int b=0; b<M; b++) {
map[a+x][b+y] -= key[a][b];
}
}
return flag;
}
}
문제 출처 : Programmers