알고리즘/백준

백준 2228번 구간 나누기 C/C++ 풀이

Chavo Kim 2020. 8. 18. 15:35

https://www.acmicpc.net/problem/2228

 

2228번: 구간 나누기

N(1≤N≤100)개의 수로 이루어진 1차원 배열이 있다. 이 배열에서 M(1≤M≤⌈(N/2)⌉)개의 구간을 선택해서, 구간에 속한 수들의 총 합이 최대가 되도록 하려 한다. 단, 다음의 조건들이 만족되어야 ��

www.acmicpc.net

이 역시 DP로 푸는 문제.

 

점화식을

 

dp[n][m](n개를 m개의 구간으로 나눴을 때의 최댓값) = dp[n-1][m](n을 포함하지 않고 m개를 선택했을 때의 최대값) 이거나 sum(i부터 n까지의 합) + dp[i - 2](하나의 공백이 있어야하기 때문에 i-2부터)[m-1](구간 하나 줄어들었으니 m-1로)'

 

으로 나타낼 수 있다.

 

 

#include <stdio.h>
#include <algorithm>

using namespace std;

FILE* in = fopen("input.txt", "r");

#define MIN -3276801

int n, m;
int arr[102];
int cache[102][52];
bool visited[102][52];
int sum_c[102][102];
bool vis_sum[102][102];

int sum(int k, int n) {
	if (vis_sum[k][n])
		return sum_c[k][n];
	int sum = 0;
	for (int i = k; i < n; i++)
		sum += arr[i];
	vis_sum[k][n] = true;
	return sum_c[k][n] = sum;
}

int dp(int n, int m) {
	if (m == 0) return 0;
	if (n <= 0)
		return MIN;
	if (visited[n][m])
		return cache[n][m];
	cache[n][m] = dp(n-1, m);
	for (int i = n - 1; i >= 0; i--)
	{
		int tmp = sum(i, n) + dp(i - 1, m - 1);
		cache[n][m] = max(tmp, cache[n][m]);
	}
	visited[n][m] = true;

	return cache[n][m];
}

int main() {
	fscanf(in, "%d %d", &n, &m);
	for (int i = 0; i < n; i++)
		fscanf(in, "%d", &arr[i]);
	printf("%d", dp(n, m));

	return 0;
}