티스토리 뷰
문제 링크 : https://www.acmicpc.net/problem/13398
13398번: 연속합 2
첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.
www.acmicpc.net
dp 문제에서 초기화는 늘 어려운 문제임을 상기시켜 주는 문제.
기본 연속합 문제에 두 가지 추가적으로 고려해야할 사항이 생겼다.
1. 적어도 하나의 수를 선택할 것. (모두 음수로 이루어지 수열의 경우를 주의해야 한다.)
2. 하나를 제거하고 연속합을 만들 수 있다.
dp[0][i] = i 를 번째 항으로 끝나는 최대 연속합
으로 정의하자. 이 경우
$$ dp[0][i]= \max( dp[0][i-1], 0) +arr[i] $$
를 점화식으로 갖게 되는데 반드시 arr[i]가 더해지므로 1 의 조건(적어도 하나가 선택)을 만족시킨다.
문제는 다음에 있다.
dp[1][i] = i 번째 항까지 하나가 제거된 최대 연속합
으로 정의했다. dp[1][0] 는 하나가 제거된 연속합이므로 dp[1][0]=0 으로 두었고
$$ dp[1][i] = \max( dp[1][i-1] +arr[i], dp[0][i-1] ) $$
의 관계식을 만족할 것 같았다.
그러나...
이렇게 하면,
길이가 1 인 수열의 경우 dp[1][0]=0 은 선택을 하나도 하지 않은 상황이 되므로 문제가 발생하고,
또한 음수로만 이루어진 경우에 ans=max(ans, blar blar~) 에서 계속 0을 선택하게 된다.
물론, 길이가 1 인 수열은 따로 거르고 추가적인 장치로 문제를 해결할 수도 있으나...
아예 dp[1][i] 의 정의를 바꾸자.
dp[1][i] = i 번까지 길이가 1 이상인 하나의 항이 제거된 연속합
이 경우 dp[1][0]은 존재하지 않으나 편의상 arr[0]으로 두면 이 후의 계산에서는 문제없이 적용된다.
#include<bits/stdc++.h>
using namespace std;
int arr[100000], dp[2][100000];
int main(){
int n; scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&arr[i]);
dp[0][0]=dp[1][0]=arr[0];
int ans=arr[0];
for(int i=1;i<n;i++){
dp[0][i]=max(dp[0][i-1],0)+arr[i];
dp[1][i]=max(dp[1][i-1]+arr[i], dp[0][i-1]);
ans=max(ans, max(dp[0][i],dp[1][i]));
}
printf("%d\n",ans);
}
다른 사람들은 어떻게 실수 없이 dp 초기화를 척척 해내는지 모르겠다.
'DS\Algo' 카테고리의 다른 글
BOJ 5735 Emoticons :-) (0) | 2022.10.08 |
---|---|
BOJ 10256 Mutation( 돌연변이 ) (0) | 2022.10.07 |
BOJ 2056 작업 (0) | 2022.10.06 |
BOJ 2302 극장 좌석 (0) | 2022.10.05 |
BOJ 9250 문자열 집합 판별 (1) | 2022.10.03 |
- Total
- Today
- Yesterday
- dynamic programming
- number theory
- bash
- Reference
- fenwick tree
- python3
- Dijkstra
- 세그먼트 트리
- BOJ
- math font
- shell
- bash script
- segment tree
- nearest common ancestor
- Shell Programming
- script
- stack
- Vim
- map
- 백준
- Aho-Corasick
- C++ big number
- 다익스트라
- max flow
- javascript array
- persistent segment tree
- 정수론
- JavaScript
- lazy propagation
- RUBY
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |