2 분 소요

1. 문제

https://www.acmicpc.net/problem/1799

  • 백트래킹 문제
// 문제
서양 장기인 체스에는 대각선 방향으로 움직일  있는 비숍(bishop) 있다. 
< 그림 1 > 같은 정사각형 체스판 위에 B라고 표시된 곳에 비숍이 있을  
비숍은 대각선 방향으로 움직여 O로 표시된 칸에 있는 다른 말을 잡을  있다.

< 그림 1 >

그런데 체스판 위에는 비숍이 놓일  없는 곳이 있다. 
< 그림 2 >에서 체스판에 색칠된 부분은 비숍이 놓일  없다고 하자. 
이와 같은 체스판에 서로가 서로를 잡을  없도록 하면서 비숍을 놓는다면 
< 그림 3 > 같이 최대 7개의 비숍을 놓을  있다.  
색칠된 부분에는 비숍이 놓일  없지만 지나갈 수는 있다.

< 그림 2 >

< 그림 3 >

정사각형 체스판의  변에 놓인 칸의 개수를 체스판의 크기라고 한다. 
체스판의 크기와 체스판  칸에 
비숍을 놓을  있는지 없는지에 대한 정보가 주어질 , 
서로가 서로를 잡을  없는 위치에 놓을  있는 
비숍의 최대 개수를 구하는 프로그램을 작성하시오.

// 입력
첫째 줄에 체스판의 크기가 주어진다. 
체스판의 크기는 10이하의 자연수이다. 
둘째 줄부터 아래의 예와 같이 
체스판의  칸에 비숍을 놓을  있는지 없는지에 대한 정보가 
체스판   단위로  줄씩 주어진다. 
비숍을 놓을  있는 곳에는 1, 
비숍을 놓을  없는 곳에는 0 빈칸을 사이에 두고 주어진다.

// 출력
첫째 줄에 주어진 체스판 위에 놓을  있는 비숍의 최대 개수를 출력한다.

// 예제 입력 1 
5
1 1 0 1 1
0 1 0 0 0
1 0 1 0 1
1 0 0 0 0
1 0 1 1 1

// 예제 출력 1 
7


2. 핵심 아이디어

  • 체스판의 검정 칸과 흰 칸을 따로 생각
  • n이 짝수인 경우 한 칸씩 이동되어 칸이 구분되는 것을 고려


3. Python 문제풀이

import sys
input = sys.stdin.readline

def check(idx) :
  c = idx % 2
  i, j = idx // n, idx % n
  for d in range(4) :
    x, y = i+dx[d], j+dy[d]
    while 0 <= x < n and 0 <= y < n:
      if visited[x*n+y] :
        return False
      x += dx[d]
      y += dy[d]
  return True

def dfs(idx, c, cnt) :
  if n * n - idx + 1 + cnt <= ans[c] or idx >= n * n : 
    return
  ans[c] = max(ans[c], cnt)
  x, y = idx // n, idx % n
  j = y
  for i in range(x, n) :
    while j < n :
      v = i * n + j
      if not visited[v] and chess[i][j] == 1 and check(v) :
        visited[v] = True
        dfs(v, c, cnt+1)
        visited[v] = False
      j += 2
    j = (c + 1) % 2 if i % 2 == 0 else c

n = int(input())
chess = [list(map(int, input().split())) for _ in range(n)]
dx, dy = [1, -1, 1, -1], [1, 1, -1, -1]
visited = [False] * (n ** 2)
ans = [0, 0]

dfs(0, 0, 0)
dfs(1, 1, 0)
print(sum(ans))


4. Java 문제풀이


댓글남기기