abs
를 쓰는 코드를 보고 무릎을 탁 쳤다.j - weight[i]
는 오른쪽에 놓는 경우, j + weight[i]
는 왼쪽에 놓는 경우를 말한다. (오른쪽에 놓는다는 것은 추를 더한다는 것이므로, 더하기 전 무게의 가능 여부를 알아야 하고, 왼쪽에 놓는다는 것은 추를 뺀다는 것으로, 빼기 전 무게의 가능 여부를 알아야 한다.)j - weight[i]
가 음수일 경우엔 무조건 불가능이도록 예외 처리를 했는데, 이를 abs(j - weight[i])
로 바꾸면, 왼쪽과 오른쪽의 추를 바꾼다는 뜻이다.abs
를 취해주는 이유이다. 2차원 dp를 사용한다.
dp\[j\]\[i\]는 i번째까지의 추를 이용해서 무게 j를 잴 수 있는지
여부이다.
최상단에서 i
를 n_weight
까지 돌리면서 추를 포함시킨다.
그 안에서 1부터 40000까지 각 구슬 무게를 잴 수 있는지에 대한 여부를 구한다.
dont
는 그 추로 아무 것도 하지 않을 때이다. 아무
left
는 weights[i]
를 왼쪽에 놓을 때이다. j + weights[i]
의 값을 가져온다.
right
는 weights[i]
를 오른쪽에 놓을 때이다. j - weights[i]
의 값을 가져온다.
단, j - weights[i]
가 음수라면 절대값을 취해준다. 이는 이전에 오른쪽에 abs(j - weights[i])
만큼의 무게를 잰 적이 있는지를 의미한다. 있다면, 그만큼의 추를 왼쪽으로 옮겨 마이너스의 무게를 만들고, 이것에 현재 오른쪽에 추가하려는 weights[i]
를 합한 무게를 잴 수 있다는 뜻이다.
import sys
scan = sys.stdin.readline
def solution():
n_weight, weights = get_input()
n_bead, beads = get_input()
dp = [[0 for _ in range(n_weight + 1)] for _ in range(40001)]
for i in range(1, n_weight + 1):
dp[weights[i]][i] = True
for j in range(1, 40001):
dont = dp[j][i - 1]
left = dp[j + weights[i]][i - 1] if j + weights[i] <= 40000 else 0
right = dp[abs(j - weights[i])][i - 1] if abs(j - weights[i]) <= 40000 else 0
dp[j][i] = dp[j][i] | dont | right | left
for i in range(1, n_bead + 1):
sys.stdout.write("%s " % ('Y' if dp[beads[i]][n_weight] else 'N'))
def get_input():
n = int(scan())
arr = [0] + list(map(int, scan().split()))
return n, arr
solution()