💡 PS
[BOJ] 16494 가장 큰 값
date
Mar 16, 2022
slug
boj-16494
author
status
Public
tags
PS
백트래킹
DP
summary
가장 큰 값 문제에 대한 풀이입니다.
type
Post
thumbnail
category
💡 PS
updatedAt
Aug 3, 2023 09:13 AM
언어
문제
풀이
처음에 dp로 문제를 풀려 했으나 좀 어려웠다. 그래서 우선 백트래킹으로 구간
le
~ ri
를 m
개 저장하여 해당 합을 구하면서 모든 경우의 수를 보았다.dp풀이는
ix
에서 i
로 가는 것을 하나의 덩어리로 보았다. cnt
가 m
개일 경우 0을 리턴해주고, ix
가 n
일 경우 덩어리 개수가 m
이 안되므로 적당히 작은 수를 리턴해주어 답이 안되게 한다. 시간복잡도는 상태가 NM
, 각 상태마다 할 수있는 행동 N
이므로, O(N^2M)
이다.코드
1) 백트래킹
#include <cstdio> #include <algorithm> #include <queue> using namespace std; typedef pair<int, int> pii; int n, m, ans = -1e9; int arr[20]; int vis[20]; vector<pii> v; int sm() { int ret = 0; for(int i = 0; i < m; i++) { int l = v[i].first, r = v[i].second; for(int j = l; j <= r; j++) ret += arr[j]; } return ret; } void go(int ix) { if (v.size() == m) { ans = max(ans, sm()); } else { int l; for(int i = ix; i < n; i++) { if (vis[i]) continue; vis[i] = 1; l = i; for(int j = l; j < n; j++) { if (vis[j] and j != i) break; vis[j] = 1; v.push_back({l, j}); go(j); vis[j] = 0; v.pop_back(); } vis[i] = 0; } } } int main() { scanf("%d %d", &n, &m); for(int i = 0; i < n; i++) scanf("%d", &arr[i]); go(0); printf("%d", ans); }
2)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n, m; int arr[20]; int dp[20][20]; int go(int ix, int cnt) { if (cnt == m) return 0; if (ix == n) return -1e9; if (dp[ix][cnt] != -1) return dp[ix][cnt]; int ret = go(ix + 1, cnt), t = 0; for(int i = ix; i < n; i++) { t += arr[i]; ret = max(ret, go(i+1, cnt + 1) + t); } return dp[ix][cnt] = ret; } int main() { memset(dp, -1, sizeof(dp)); scanf("%d %d", &n, &m); for(int i = 0; i < n; i++) scanf("%d", &arr[i]); printf("%d", go(0, 0)); }