조건
- N : 체스판 크기, 1~10 이하 자연수
- 비숍은 사방 대각선으로 공격 가능
접근 방법
- 체스판의 검은 영역 과 흰 영역 을 분리해 생각
- 큰 덩어리를 둘로 분리해 작은 덩어리 두 번 계산
- 시간복잡도
- 영역을 분리하지 않은 경우 : O(2 ^ (N*N)) => 각각의 체스칸마다(N*N개) 비숍을 놓을 지 말지 선택(2가지)
- 영역을 분리한 경우 : O(2 ^ (N/2 * N/2)) => 각각의 체스칸마다(N/2*N/2개) 비숍을 놓을 지 말지 선택(2가지) * 2(흰 영역, 검은 영역 두 번 계산)
솔루션
public class Main_1799_비숍 {
static int N, size, max;//map N*N
static int[][] map;//체스판
static int[] dr = {-1,-1,1,1};//대각선
static int[] dc = {-1,1,-1,1};
static List<int[]> black, white;//비숍 놓을 수 있는 칸 정보
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
N = Integer.parseInt(br.readLine().trim());
map = new int[N][N];
black = new ArrayList<int[]>();
white = new ArrayList<int[]>();
for(int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine().trim(), " ");
for(int j = 0; j < N; j++) {
if(st.nextToken().charAt(0) == '1') {//빈칸
if((i+j) % 2 == 0) black.add(new int[] {i,j});
else white.add(new int[] {i,j});
map[i][j] = 0;
}else {//비숍 놓을 수 X
map[i][j] = -1;
}
}
}
//체스 검은칸 개수 => O(2 ^ (N/2 * N/2))
size = black.size();//빈칸 개수
dfs(0,0, black);
int black = max;
//체스 흰칸 개수 => O(2 ^ (N/2 * N/2))
size = white.size();
max = 0;
dfs(0,0, white);
System.out.println(black + max);
}
//empty 리스트 인덱스, 이제까지 비숍 놓은 개수, 빈칸 영역
private static void dfs(int idx, int cnt, List<int[]> empty) {
if(max < cnt) max = cnt;
int[] point;
int r,c,nr,nc;
for(int i = idx; i < size; i++) {
point = empty.get(i);
r = point[0];
c = point[1];
if(map[r][c] > 0) {//다른 곳에 놓은 비숍의 공격 범위에 있는 경우
continue;
}
map[r][c] = 1;//비숍 놓음
//비숍 공격범위 체크
for(int k = 0; k < 4; k++) {
nr = r + dr[k];
nc = c + dc[k];
while(nr > -1 && nr < N && nc > -1 && nc < N) {
if(map[nr][nc] > -1) {//-1이면 원래 못놓는 곳
map[nr][nc]++;
}
nr += dr[k];
nc += dc[k];
}
}
dfs(i+1, cnt+1, empty);
map[r][c] = 0;//놓았던 비숍 지움
//비숍 공격범위 지우기
for(int k = 0; k < 4; k++) {
nr = r + dr[k];
nc = c + dc[k];
while(nr > -1 && nr < N && nc > -1 && nc < N) {
if(map[nr][nc] > -1) {//-1이면 원래 못놓는 곳
map[nr][nc]--;
}
nr += dr[k];
nc += dc[k];
}
}
}
}
}
리뷰
- 처음에 체스판의 검은 영역 과 흰 영역 을 분리해 생각하지 못함(어떻게 생각해냄 이런거를..?)
- 같은 로직을 위와같이 절반으로 나누면 시간복잡도가 훨씬 줄어듦..!!
'알고리즘 > DFS&BFS(깊이&너비 우선 탐색)' 카테고리의 다른 글
백준_가르침_1062 (1) | 2021.01.27 |
---|---|
백준_암호만들기_1759 (0) | 2021.01.25 |
백준_욕심쟁이판다_1937 (0) | 2021.01.20 |
백준_미로만들기_2665 (0) | 2021.01.13 |
백준_부등호_2529 (0) | 2021.01.06 |