[문제]
- N: 마을의 수 (2 ≤ N ≤ 100,000)
- Ai: 이웃한 마을간 산책로의 수 (1 ≤ Ai ≤ 1,000,000,000 십억)
- 산책을 출발하면 이웃한 마을로만 이동이 가능하며, 한번 지난 산책로는 다시 지나지 않는다.
- 어떤 마을에서든 산책을 시작할 수 있고, 어떤 마을에서든 마칠 수 있다.
[알고리즘]
DP
[Key Point]
- 임의의 마을(Ai) 은 아래 세 가지 경우를 포함한다.
. L[Back] + R[Back] : 좌우를 모두 다녀오는 경우
. L[Go] + R[Back] : 우측을 돌고 좌측으로 가는 경우
. L[Back] + R[Go] : 좌측을 돌과 우측으로 가는 경우
- 점화식:
L[i][Back] = L[i-1][Back] + 짝수(r[i-1])
R[i][Back] = R[i+1][Back] + 짝수(r[i])
L[i][Go] = max(L[i-1][Back], L[i-1][Go]) + 홀수(r[i-1])
R[i][Go] = max(R[i+1][Back], R[i+1][Go]) + 홀수(r[i])
[구현코드]
// test-p0081.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
// 유사문제: 팀구성
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX_N = 100002;
enum { GO = 0, BACK};
int T, N;
int r[MAX_N];
long long L[MAX_N][2];
long long R[MAX_N][2];
int c[2];
long long ans[MAX_N];
void GetRoadCount(const long long roads)
{
if (roads == 1) {
c[GO] = 1;
c[BACK] = 0;
}
else if (roads % 2 == 0) {
c[GO] = roads - 1;
c[BACK] = roads;
}
else {
c[GO] = roads;
c[BACK] = roads - 1;
}
}
int main()
{
setbuf(stdout, NULL);
#ifdef _DEBUG
freopen("input2.txt", "r", stdin);
#endif
scanf("%d", &T);
for (int tc = 1; tc <= T; tc++) {
scanf("%d", &N);
memset(&r, NULL, sizeof(r));
memset(&L, NULL, sizeof(L));
memset(&R, NULL, sizeof(R));
memset(&ans, NULL, sizeof(ans));
for (int i = 1; i < N; i++) {
scanf("%d", &r[i]);
}
for (int i = 2; i <= N; i++) {
GetRoadCount(r[i - 1]);
L[i][GO] = max(L[i - 1][GO], L[i - 1][BACK]) + c[GO];
L[i][BACK] = L[i - 1][BACK] + c[BACK];
if (r[i - 1] == 1) {
L[i][BACK] = 0;
}
}
for (int i = N-1; i >= 1; i--) {
GetRoadCount(r[i]);
R[i][GO] = max(R[i + 1][GO], R[i + 1][BACK]) + c[GO];
R[i][BACK] = R[i + 1][BACK] + c[BACK];
if (r[i] == 1) {
R[i][BACK] = 0;
}
}
ans[1] = max(R[1][GO], R[1][BACK]);
ans[N] = max(L[1][GO], L[1][BACK]);
long long answer = max(ans[1], ans[N]);
for (int i = 2; i < N; i++) {
ans[i] = max(L[i][BACK] + R[i][BACK], max(L[i][BACK] + R[i][GO], L[i][GO] + R[i][BACK]));
answer = max(answer, ans[i]);
}
printf("#%d %lld\n", tc, answer);
}
}
더보기
(입력)
5
5
3 1 2 1
5
4 1 1 2
3
2 2
7
1 2 3 4 5 6
13
1 1 1 1 1 1 1 1 1 1 1 1
(출력)
#1 6
#2 8
#3 4
#4 19
#5 12
'배움의공간(學) > 알고리즘' 카테고리의 다른 글
[백준] 2252-줄 세우기 (0) | 2021.04.05 |
---|---|
[기출] 디자이너의 고민 (0) | 2021.02.10 |
[그래프] 사이클 찾기 (0) | 2021.02.05 |
기본 알고리즘 (0) | 2020.12.14 |
알고리즘 학습 (0) | 2020.10.20 |
댓글