Skip to content

Commit f19a995

Browse files
committed
[Week13] PGS 60059: 자물쇠와 열쇠
1 parent 3348673 commit f19a995

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package study.week13;
2+
3+
// 자물쇠와 열쇠
4+
// 구현, 브루트포스
5+
/**
6+
* 자물쇠 배열과, 키 배열을 매핑하여 겹치는 부분 없이 자물쇠 배열을 전부 채우면 true, 아니면 false 인 문제
7+
* 1. key 를 회전시켜서 (0,90, 180, 270) 자물쇠와 대조 할 수 있다.
8+
* 2. key 를 이동시켜서 키의 부분을 자물쇠와 매핑 가능하다(자물쇠를 넘어가는 부분은 상관 없음)
9+
* 풀이의 키 포인트는, 모든 경우의 수를 대조 해 보기 위해 배열 확장과, rotate이다.
10+
* 배열 확장: key의 일부분만 자물쇠에 대조 해 볼 수 있기 때문에, 키가 위치할 수 있는 모든 가능성을 열어둔 N(자물쇠) + (2*(N-1))(키) 사이즈의 배열을 선언한 후 가운데에 자물쇠를 둔다
11+
* rotate : 열과 행을 반전(회전, 열과 행의 길이가 다를 수 있음), rotate[i][j] = arr[n-1-j][i] 로직으로 시계방향 90도 회전, n은 y값 size
12+
* 또한, 자물쇠의 좌측 상단 idx를 기반으로 확장 자물쇠 배열의 모든 상황을 테스트 해 봐야 한다.
13+
* i < length(확장 자물쇠 배열size) - M(key size), j<length(확장 자물쇠 배열 size) - M(key size)
14+
* (i, j)에서 key의 배열을 자물쇠 배열에 값을 더한 후, check, check 결과가 true 면 즉시종료
15+
* check는 자물쇠 범위에서 하나라도 1이 아니면 false, 1이상이 될 수도 있다(자물쇠와 key가 겹치는 부분이 존재해도 false)
16+
*/
17+
public class PGS_60059 {
18+
19+
class Solution {
20+
21+
int N;
22+
int M;
23+
int length;
24+
25+
public boolean solution(int[][] key, int[][] lock) {
26+
N = lock.length;
27+
M = key.length;
28+
29+
// 자물쇠를 정중앙에 두고 열쇠가 걸칠 수 있도록 확장 배열 생성
30+
length = N + (M - 1) * 2;
31+
int[][] arr = new int[length][length];
32+
33+
// 1. 확장 배열의 중앙에 자물쇠 값 복사
34+
for (int i = 0; i < N; i++) {
35+
for (int j = 0; j < N; j++) {
36+
arr[i + M - 1][j + M - 1] = lock[i][j];
37+
}
38+
}
39+
40+
// 2. 4가지 방향으로 회전하며 탐색
41+
for (int r = 0; r < 4; r++) {
42+
key = rotate(key);
43+
44+
// 3. 확장 배열 위를 슬라이딩 하며 열쇠 꽃아보기
45+
// i, j 는 열쇠가 위치할 좌측 상단 좌표
46+
for (int i = 0; i <= length - M; i++) {
47+
for (int j = 0; j <= length - M; j++) {
48+
49+
// [열쇠 꽃기] 현재 위치에열쇠 값 더하기
50+
for (int x = 0; x < M; x++) {
51+
for (int y = 0; y < M; y++) {
52+
arr[i + x][j + y] += key[x][y];
53+
}
54+
}
55+
56+
// [검증] 자물쇠 영역이 모두 1이 되었는지 확인
57+
if (check(arr)) {
58+
return true;
59+
}
60+
61+
// [원상 복구] 맞지 않다면 다음 탐색을 위해 더했던 열쇠 값 다시 빼기
62+
for (int x = 0; x < M; x++) {
63+
for (int y = 0; y < M; y++) {
64+
arr[i + x][j + y] -= key[x][y];
65+
}
66+
}
67+
}
68+
}
69+
}
70+
71+
// 4방향, 모든 위치를 다 했는데도 true 반환 안되면 열수없는 자물쇠
72+
return false;
73+
}
74+
75+
int[][] rotate(int[][] arr) {
76+
int n = arr.length;
77+
int m = arr[0].length;
78+
int[][] rotate = new int[m][n]; // 새로운 배열은 m행 n열로 선언하여 회전 후 배열 구조를 미리 만들어 놓아야 한다.
79+
80+
for (int i = 0; i < rotate.length; i++) {
81+
for (int j = 0; j < rotate[i].length; j++) {
82+
rotate[i][j] = arr[n - 1 - j][i];
83+
}
84+
}
85+
86+
return rotate;
87+
}
88+
89+
boolean check(int[][] arr) {
90+
for (int i = 0; i < N; i++) {
91+
for (int j = 0; j < N; j++) {
92+
if (arr[i + M - 1][j + M - 1] != 1) {
93+
return false;
94+
}
95+
}
96+
}
97+
return true;
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)