문제 : https://www.acmicpc.net/problem/2629
배낭문제(knapsack problem)를 응용한 문제이다.(12865번 문제 참고)
점화식을 아래처럼 설계한다.
dp[i][j]=i번째 추를 넣을경우, 안넣을경우, 반대편에 넣을경우 만들 수 있는 구슬의무게
즉, i-1번째 무게가 weight이고 i번째 추의 무게가 j인 경우
위의 3가지는 구슬의 무게로 가능한 가짓 수 이다.
이때,
N=int(input())
li=[0]+list(map(int,input().split()))+[0]
ball_N=int(input())
ball=list(map(int,input().split()))
dp=[[0]*(15001) for i in range(N+1)]
def back(now,weight):
if now>N or dp[now][weight]:
return
dp[now][weight]=1
back(now+1,weight+li[now+1])
back(now+1,abs(weight-li[now+1]))
back(now+1,weight)
back(0,0)
for i in ball:
ch=0
if i>15000:
print("N",end=" ")
else:
for j in range(1,N+1):
if dp[j][i]==1:
print("Y",end=" ")
ch=1
break
if ch==0:
print("N",end=" ")
아래의 방법은 2차원 dp배열 대신 set을 이용한 방법이다.
위와 같은 방법으로 이루어지지만, set을 이용해 훨씬 간결하게 작성된 방법.
N=int(input())
li=list(map(int,input().split()))
ball_N=int(input())
ball=list(map(int,input().split()))
dp_set=set()
for weight in li:
tmp_set=set()
tmp_set.add(weight)
for i in dp_set:
tmp_set.add(weight+i)
tmp_set.add(abs(weight-i))
dp_set=dp_set.union(tmp_set)
for i in ball:
print("Y" if i in dp_set else"N",end=" ")