알고리즘 문제 풀이
우선 완전 탐색을 할 방법을 찾는다.
dfs로 해결하는 방식도 괜찮지만, 문득 라이언이 이겨야만 하는 경우에 대해 해당 위치를 지정하고, 조건을 만족할 수 있는지 확인하는 방법을 사용하면 되지 않을까? 라고 생각하였다. 따라서 이긴 경우 비트를 1, 졌을 경우 비트를 0으로 두어 모든 경우에 대하여 탐색했다. 현재 경우 총 배열의 길이가 11이므로 2 ** 11 = 2048가지의 경우만 존재할 수 있으므로 탐색에 대하여 문제될 것이 없다. (배열의 길이가 짧기 때문에 완전 탐색을 시도해 보라는 문제의 의도도 알 수 있다)
1
: 라이언이 해당 점수를 어피치보다 많이 맞춰서 점수를 가져오는 경우
0
: 라이언이 해당 점수를 가져올 수 없는 경우
비트를 사용하여 모든 경우를 탐색하는 방법은 다음과 같다.
for i in range(1 << 11): # 2048가지의 경우에 대하여 탐색
for j in range(11):
if (1 << j) & i:
# do something
해당 비트 연산자에서의 조건을 만족할 수 있는지 확인한다.
확인 하는 과정은 비트가 1인 위치에서 어피치가 해당 점수에서 맞춘 화살의 개수 + 1을 모두 더하고, 모두 더한 값이 n을 초과한다면 불가능한 경우의 수 이므로 해당 경우는 기록하지 않는다.
비트를 배열로 변환한다.
배열을 반환하기 위해서는 비트를 배열로 바꿔야 한다.
변환한 배열의 합이 n이 되는지 확인한다.
배열의 합이 n이라면, n개의 화살을 전부 명중시켰다는 뜻으로 다른 위치에 화살을 맞출 필요가 없으므로 다음단계로 이동한다.
나머지는 코드로 확인하자.
INF = 987654321
def solution(n, info):
max_score = 0
case = INF
score_board = [0] * 11
for i in range(1 << 11):
count = 0
for j in range(11):
if (1 << j) & i:
count += info[10 - j] + 1
if count > n:
continue
next_score = calculate(info, i)
next_score_board = transform(info, i)
s = sum(next_score_board)
if s < n:
for i in range(10, -1, -1):
if next_score_board[i] == 0:
next_score_board[i] += n - s
break
if next_score > max_score:
max_score = next_score
case = i
score_board = next_score_board[:]
elif next_score == max_score:
score_board = compare(score_board, next_score_board)
if case == INF:
return [-1]
return score_board
def calculate(info, score_board):
a, b = 0, 0
for i in range(11):
if (1 << i) & score_board:
a += i
elif info[10 - i] > 0:
b += i
return a - b
def transform(info, score_board):
ret = [0] * 11
for i in range(11):
if (1 << i) & score_board:
ret[10 - i] = info[10 - i] + 1
return ret
def compare(prev, next):
for i in range(10, -1, -1):
if prev[i] > next[i]:
return prev
if prev[i] < next[i]:
return next
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
n = 10
info = [0,0,0,0,0,0,0,0,3,4,3]
print(solution(n, info))
for j in range(11):
if (1 << j) & i:
count += info[10 - j] + 1 # 정답
for j in range(11):
if (1 << j) & i:
count += info[j] + 1 # 오답
앞으로는 배열과 비트마스킹을 혼합하여 사용할 경우 좀 더 세심한 고려를 해야겠다.
case
변수의 모호성(일단 조건을 하나라도 만족하는지를 판별하기 위하여 사용되고 있지만, 해당 조건은 한 번 밖에 사용되지 않음), 그리고 max_score과 배열의 진짜 score간의 차이가 존재할 수 있다는 것이다. 다른 방법으로 해결할 수 있는지 조금 더 고민해 봐야겠다.