https://www.acmicpc.net/problem/1799
1799번: 비숍
첫째 줄에 체스판의 크기가 주어진다. 체스판의 크기는 10이하의 자연수이다. 둘째 줄부터 아래의 예와 같이 체스판의 각 칸에 비숍을 놓을 수 있는지 없는지에 대한 정보가 체스판 한 줄 단위로
www.acmicpc.net
이 문제는 백트레킹 문제중에서
난이도가 상당히 높은 문제.
우선 제가 초기에 풀었을 때는
'정석(?)'대로
대각선이 비어있는지 확인해주고
비숍을 넣는 방식이었습니다.
import sys
sys.setrecursionlimit(10**8)
N=int(input())
room=[list(map(int,input().split())) for _ in range(N)]
ga=[False]*(2*N-1)
sa=[False]*(2*N-1)
answer=0
def dfs(x,y,bi):
global answer
if y==N:
dfs(x+1,0,bi)
return
if x==N:
answer=max(answer,bi)
return
if room[x][y]==1:
if ga[x+y]==False and sa[x-y+N-1]==False:
ga[x+y]=True
sa[x-y+N-1]=True
dfs(x,y+1,bi+1)
ga[x+y]=False
sa[x-y+N-1]=False
dfs(x,y+1,bi)
return
dfs(0,0,0)
print(answer)
이 방식은 시간초과가 바로 발생했습니다.
문제 곧이 곧대로 풀었는데
무슨 방법이 더 있나...
구글링해서 알아낸 힌트는
흰색,검은색을 따로 분리해서 계산하는 방법.
체스판에서는 흰색,검은색이
각각 지그제그로 표시가 되어있습니다.
비숍을 흰색 칸에 두면
비숍은 흰색 칸만 움직이고
검은색칸에 두면
검은색 칸만 움직이죠.
그래서
'흰색칸을 넣을때 최대'
'검은색칸을 넣을 떄 최대'
각각을 구한다음에 더해주는 방식이었죠.
N=int(input())
room=[list(map(int,input().split())) for _ in range(N)]
black=[]
white=[]
color=[[0]*N for _ in range(N)]
for x in range(N):
for y in range(N):
if (x+y)%2==0:
color[x][y]=0
if room[x][y]==1:
black.append((x,y))
else:
color[x][y]=1
if room[x][y]==1:
white.append((x,y))
w_cnt=0
b_cnt=0
da=[False]*(2*N-1)
da_2=[False]*(2*N-1)
def put(box,index,count):
global w_cnt,b_cnt
if index==len(box):
if box==white:
w_cnt=max(w_cnt,count)
else:
b_cnt=max(b_cnt,count)
return
x,y=box[index]
if da[x+y] or da_2[x-y+N-1]:
put(box,index+1,count)
else:
da[x+y]=True
da_2[x-y+N-1]=True
put(box,index+1,count+1)
da[x+y]=False
da_2[x-y+N-1]=False
put(box,index+1,count)
if len(white)>0:
put(white,0,0)
if len(black)>0:
put(black,0,0)
print(w_cnt+b_cnt)
백트레킹을 어떻게 하면
시간을 줄일 수 있을지
생각하게 만들어준 좋은 문제입니다.
[삼성sw 5644번]무선충전(파이썬) (0) | 2022.10.10 |
---|---|
[코드트리] 정육면체 한번 더 굴리기(파이썬) 2021 하반기 삼성코딩테스트 기출 (0) | 2022.10.08 |
[백준 5427] 불(파이썬) (0) | 2022.10.08 |
[코드트리] 나무박멸(파이썬) -2022 삼성sw 상반기 코테 기출 (0) | 2022.10.07 |
[코드트리] 술래잡기(파이썬) 2022 삼성 코딩테스트 상반기 기출 (0) | 2022.10.06 |
댓글 영역