티스토리 뷰
https://www.acmicpc.net/problem/1126
처음에 봤을 땐 그리디로 큰 값부터 작은 위치에 값을 더하는 방식으로 하고 싶지만 그러면 틀리게 된다.
이 문제는 dp 문제인데 i번째 블록을 움직일 수 있는 경우는 왼쪽 탑에 올린다, 오른쪽 탑에 올린다, 버린다
이렇게 3가지의 경우가 있다. 이때 왼쪽 탑과 오른쪽 탑으로 분리하지 말고 왼쪽 탑과 오른쪽 탑과의 높이 차로 dp 테이블을 만들 수 있다.
그럼 이렇게 정의하자 dp [i][j]=i부터 n까지 높이차가 j일 때 최대 높이
이제 테이블을 구현해보자 i번째에서 사용하지 않는 경우인 dp [i+1][j]와 높은 쪽에 올리는 경우 dp [i+1][j+input [i]], 낮은 곳에 올리는 경우 dp [i+1][abs(input [i]-j)]+min(input [i], j) 3가지를 이렇게 구현할 수 있다. 이때 낮은 곳에 올리는 경우에서 +min(input [i], j)를 추가한 이유는 최대 높이를 구해야 되기 때문에 낮은 높이에 올린 값을 더하기 위해서이다. 또 높은 곳에 올리는 경우일 때 더하지 않은 이유는 높은 곳에 올리면 i+1번째에서 낮은 곳에 올릴 때 최대 값을 만들 수 있기 때문에 더하지 않는다.
이제 이 모든 값들중 가장 큰 값을 저장하면 된다.
즉 dp[i][j]=max([dp[i+1][j],dp[i+1][j+input[i]],dp[i+1][abs(input[i]-j)]+min(input[i],j)]) 이 된다.
이때 dp[0][0]이 0일 경우 만들 수 없는 것이기 때문에 -1을 출력하면 된다.
import sys,math
inf=math.inf
input=sys.stdin.readline
a=int(input())
l=list(map(int,input().split()))
dp=[[-1 for g in range(500002)] for i in range(a+1)]
if a==1:print(-1);sys.exit()
if a==2:
if l[0]==l[1]:print(l[0])
else:print(-1)
sys.exit()
for i in range(a,-1,-1):
for j in range(500002):
if j==500001:dp[i][j]=-inf
if i==a:
if j==0:dp[i][j]=0
else:dp[i][j]=-inf
else:
dp[i][j]=max([dp[i+1][j],dp[i+1][min(500001,j+l[i])],dp[i+1][abs(l[i]-j)]+min(l[i],j)])
ans=dp[0][0]
print('-1'if ans==0 else ans)
'ps' 카테고리의 다른 글
BOJ 20149(선분 교차 3)풀이 (0) | 2021.08.14 |
---|---|
BOJ 6164(Hotel)풀이 (0) | 2021.08.07 |
BOJ 22348(헬기 착륙장)풀이 (1) | 2021.08.01 |
BOJ 1915(가장 큰 정사각형)풀이 (0) | 2021.07.15 |
BOJ 12784(인하니카 공화국)풀이 (0) | 2021.07.05 |
- Total
- Today
- Yesterday
- 세그먼트 트리
- 개발
- 느리게 갱신되는 세그먼트 트리
- 그리디 알고리즘
- 트리
- 정렬
- 수학
- 알고리즘
- A Dance of Fire and Ice
- 이분매칭
- 잡봇
- 자료 구조
- 트리에서의 다이나믹 프로그래밍
- 그래프 탐색
- codeforces
- 다이나믹 프로그래밍
- C++
- 깊이 우선 탐색
- KOI
- 그래프 이론
- 최소 스패닝 트리
- 이분 탐색
- 구현
- discord bot
- Python
- 자료구조
- 선분 교차 판정
- 완전 탐색
- BOJ
- 누적 합
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |