2차원 동전 뒤집기
문제 설명
한수는 직사각형 모양의 공간에 놓인 동전들을 뒤집는 놀이를 하고 있습니다. 모든 동전들은 앞과 뒤가 구분되어 있으며, 동전을 뒤집기 위해서는 같은 줄에 있는 모든 동전을 뒤집어야 합니다. 동전들의 초기 상태와 목표 상태가 주어졌을 때, 초기 상태에서 최소 몇 번의 동전을 뒤집어야 목표 상태가 되는지 알아봅시다.

예를 들어, 위 그림에서 맨 왼쪽이 초기 상태, 맨 오른쪽이 목표 상태인 경우에 대해 알아봅시다. 그림에서 검은색 원은 앞면인 동전, 흰색 원은 뒷면인 동전을 의미합니다. 초기 상태에서 2행과 4행의 돌들을 뒤집으면, 두 번째 그림이 됩니다. 그 후, 2열, 4열, 5열의 돌들을 순서대로 뒤집는 다면, 총 5번의 동전 뒤집기를 통해 목표 상태가 되며, 이 경우가 최소인 경우입니다.
직사각형 모양의 공간에 놓인 동전들의 초기 상태를 나타내는 2차원 정수 배열 beginning, 목표 상태를 나타내는 target이 주어졌을 때, 초기 상태에서 목표 상태로 만들기 위해 필요한 동전 뒤집기 횟수의 최솟값을 return 하는 solution 함수를 완성하세요. 단, 목표 상태를 만들지 못하는 경우에는 -1을 return 합니다.
첨엔 순열 생각했다가, 조합으로 풀었다. 조합으로 풀긴했는데, 가지치기 요런건 하나도 안해서 시간이 꽤 오래걸린다.
다른 사람들 보면 비트마스킹이나 판별 메서드 만들어 놓고, 여러 방식으로 가지 치기했는데 시간초과나면 가지치지뭐.. 라는 생각으로 우선 풀고 다행히 시간 초과가 나지 않았따.
class Solution {
static int N, M,answer=100000;
static boolean[] visitedR;
static boolean[] visitedC;
public int solution(int[][] beginning, int[][] target) {
N = beginning.length;
M = beginning[0].length;
visitedR = new boolean[N];
visitedC = new boolean[M];
dfs(beginning,target,0,0,0,0);
if(answer==100000)return -1;
return answer;
}
private static void dfs(int[][] beginning, int[][] target, int depthR, int depthC, int rCnt, int cCnt){
if(depthR>N || depthC>M)return;
if(answer<=rCnt+cCnt)return;
if(compare(beginning, target) ){
answer = Math.min(answer,rCnt+cCnt);
return;
}
for(int i=depthR; i<N; i++){
//행 뒤집기
if(visitedR[i])continue;
visitedR[i]=true;
for(int j=0;j<M;j++)beginning[i][j]= beginning[i][j]==1 ? 0 : 1;
dfs(beginning,target,i+1,depthC,rCnt+1,cCnt);
for(int j=0;j<M;j++)beginning[i][j]= beginning[i][j]==1 ? 0 : 1;
visitedR[i]=false;
}
for(int i=depthC; i<M; i++){
if(visitedC[i])continue;
visitedC[i]=true;
for(int j=0;j<N;j++)beginning[j][i]= beginning[j][i]==1 ? 0 : 1;
dfs(beginning,target,depthR,i+1,rCnt,cCnt+1);
for(int j=0;j<N;j++)beginning[j][i]= beginning[j][i]==1 ? 0 : 1;
visitedC[i]=false;
}
}
private static boolean compare(int[][] beginning, int[][] target){
for(int i =0;i<N; i++)
for(int j =0; j<M; j++)
if(beginning[i][j]!=target[i][j])return false;
return true;
}
}
나중에 다시 풀텐데, 그땐 비트마스킹이나 자체 가지치기함수를 추가해서 좀 더 시간을 줄여보도록 하겠다.