Algorithm, kakao2018 프렌즈4블록(17679)
어려웠던점
- 개념적으로 해결할 방법은 알아냈으나, 코드로 구현하기가 어려웠다.
- 맵을 새로 리뉴얼 하는 부분이 어려웠다 (해결 코드의 down()함수)
- 네개를 비교 하는 부분은 for문과 배열을 이용해서 쉽게 구현할 수 있었다
풀이
- map전체를 돌며 하나씩 해당 위치의 네방향을 비교하여 삭제가능한지 알아낸다. 삭제가능하면 visited = true로 만든다
- visited = true로 만드는 이유 : 삭제가능하다고 바로 삭제해버리면 예제처럼 겹치는 부분은 삭제가 되지 않기 때문에 일단, 삭제 가능 한 부분을 표시해준다.
- 처음 방문하는 위치라면 cnt++를 해주어 삭제할 개수를 세어준다
for (int i = 0; i < m-1; i++) {
for (int j = 0; j < n-1; j++) {
char c = map[i][j];
if(c == '.') continue;
boolean same = true;
for (int k = 0; k < 4; k++) {
if(map[i+dx[k]][j+dy[k]] != c) {
same = false;
break;
}
}
if(!same) continue;
for (int k = 0; k < 4; k++) {
int nx = i+dx[k];
int ny = j+dy[k];
if(!visited[nx][ny])
cnt++;
visited[nx][ny] = true;
}
}
}
- 전체 map에서 삭제가능한것들을 visited 배열에 입력하면 map에 삭제 가능한것들을 ‘.’ 으로 변경하여 삭제해버린다.
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if(visited[i][j])
map[i][j] = '.';
}
}
- cnt == 0 이라는 의미는 더이상 2x2로 삭제할 것이 없으니까 그만 하라는 의미이다. 따라서 break로 while문을 나간다
- cnt == 0이 아니면 해당 라운드에서 삭제한 cnt값을 answer에 더한다
if(cnt == 0) break;
answer += cnt;
- down 메소드는 삭제할것들을 삭제하여 map을 다시 만드는 함수이다
- map의 맨아래 행에서 위로 올라가며 조사하는데
- 삭제할것이 있으면 (‘.’이 있으면) 건너뛰고 삭제할것이 없으면 그 아래칸을 조사한다 ( map[nx+1][j] )
- 그 아래칸이 삭제할것이 아니라면 해당칸에 해당 문자를 넣고
- 그 아래칸이 삭제할것 이라면 nx++;을 해서 삭제할것이 아닐때까지 더해주고(내려가고) , 더이상 삭제할칸이 없으면 그 위칸에 map[nx][j] = c; 문자를 넣어준다
public static void down(int m, int n, char[][] map) {
for (int i = m-1; i >= 0 ; i--) {
for (int j = 0; j < n; j++) {
if(map[i][j] == '.') continue;
int nx = i;
char c = map[i][j];
map[i][j] = '.';
while(true) {
if(nx+1 >= m || map[nx+1][j] != '.') break;
nx++;
}
map[nx][j] = c;
}
}
}
전체코드
package org.programmers;
public class kakao_2018_17679_fiends4block_finish {
static int[] dx = {0,0,1,1};
static int[] dy = {0,1,0,1};
public static int solution(int m, int n, String[] board) {
int answer = 0;
char[][] map = new char[m][n];
boolean[][] visited;
for (int i = 0; i < m; i++) {
map[i] = board[i].toCharArray();
}
while(true) {
visited = new boolean[m][n];
int cnt = 0;
for (int i = 0; i < m-1; i++) {
for (int j = 0; j < n-1; j++) {
char c = map[i][j];
if(c == '.') continue;
boolean same = true;
for (int k = 0; k < 4; k++) {
if(map[i+dx[k]][j+dy[k]] != c) {
same = false;
break;
}
}
if(!same) continue;
for (int k = 0; k < 4; k++) {
int nx = i+dx[k];
int ny = j+dy[k];
if(!visited[nx][ny]) cnt++;
visited[nx][ny] = true;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if(visited[i][j])
map[i][j] = '.';
}
}
if(cnt == 0) break;
answer += cnt;
down(m,n,map);
}
return answer;
}
public static void down(int m, int n, char[][] map) {
for (int i = m-1; i >= 0 ; i--) {
for (int j = 0; j < n; j++) {
if(map[i][j] == '.') continue;
int nx = i;
char c = map[i][j];
map[i][j] = '.';
while(true) {
if(nx+1 >= m || map[nx+1][j] != '.') break;
nx++;
}
map[nx][j] = c;
}
}
}
}
Reference