λμ κ³νλ²(Dynamic Programming)
볡μ‘ν λ¬Έμ λ₯Ό κ°λ¨ν μ¬λ¬ κ°μ λ¬Έμ λ‘ λλμ΄ νΈλ λ°©λ²μ΄λ€.
- λκ°μ μ°μ°μ λ°λ³΅νμ§ μλλ‘ λ§λ€μ΄ μ£Όκ³ μ€ν μκ°μ μ€μΌ μ μλ€.
- μμ λ¬Έμ λ€μ νμ΄λκ°λ€ 보면 μ΄μ μ ꡬν΄λ λ μμ λ¬Έμ λ€μ΄ νμ©λλ κ²μ νμΈνκ² λλ€. μ΄μ λν κ·μΉμ μ°Ύμμ λ μ νμμ λμΆν΄ λ΄μ΄ λμ κ³νλ²μ μ μ©νλ€.
νμ΄λ²
- dp[i]κ° μλ―Ένλ λ°
- dp[i]λ₯Ό initialize νλ λ°©λ²
- dp[i]μ μ νμ
- dp[i]λ₯Ό μ±μ°λ μμ
- μ λ΅μ΄ μλ―Ένλ λ°
λ¬Έμ
https://www.acmicpc.net/problem/1932
#include <iostream>
#include <algorithm>
using namespace std;
int dp[501][501];
int main()
{
int n;
cin >> n;
int result = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++) {
cin >> dp[i][j];
if (j == 1) // μΌμͺ½ λκ°μ
dp[i][j] += dp[i - 1][j];
else if (i == j) // μ€λ₯Έμͺ½ λκ°μ
dp[i][j] += dp[i - 1][j - 1];
else
dp[i][j] += max(dp[i - 1][j], dp[i - 1][j - 1]);
if (result < dp[i][j])
result = dp[i][j];
}
cout << result;
}
https://www.acmicpc.net/problem/1463
#include <iostream>
#include <algorithm>
using namespace std;
int dp[1000001];
int main()
{
int n;
cin >> n;
dp[1] = 0;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + 1;
if (i % 2 == 0 && dp[i / 2] + 1 <= dp[i])
dp[i] = dp[i / 2] + 1;
if (i % 3 == 0 && dp[i / 3] + 1 <= dp[i])
dp[i] = dp[i / 3] + 1;
}
cout << dp[n];
}
https://www.acmicpc.net/problem/1912
#include <iostream>
#include <algorithm>
using namespace std;
int dp[100001];
int main()
{
int n;
cin >> n >> dp[0];
for (int i = 1; i < n; ++i) {
cin >> dp[i];
dp[i] = max(dp[i], dp[i - 1] + dp[i]);
}
cout << *max_element(dp, dp + n);
}
https://leetcode.com/problems/longest-valid-parentheses/
#include <vector>
#include <string>
#include <stack>
using namespace std;
class Solution {
public:
int longestValidParentheses(string s) {
int answer = 0;
stack<int> st;
vector<int> dp(s.size(), 0);
for (int i = 0; i < s.size(); i++) {
char c = s[i];
if (c == '(')
st.push(i);
else {
if (st.empty())
continue;
int index = st.top();
st.pop();
dp[i] = i - index + 1 + (index > 0 ? dp[index - 1] : 0);
}
answer = max(answer, dp[i]);
}
return answer;
}
};
λ¬Έμ : μ°μ κ°μ΄ λΆκ°λ₯ν λ μ΅λκ° κ΅¬νκΈ°
https://www.acmicpc.net/problem/2579
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
int stair[300], dp[300];
for (int i = 0; i < n; i++)
cin >> stair[i];
dp[0] = stair[0];
dp[1] = stair[0] + stair[1];
dp[2] = max(stair[1] + stair[2], stair[0] + stair[2]);
for (int i = 3; i < n; i++)
dp[i] = max(stair[i] + dp[i - 2], stair[i] + stair[i - 1] + dp[i - 3]);
cout << dp[n - 1];
}
https://www.acmicpc.net/problem/2156
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
int grape[10001];
for (int i = 1; i <= n; ++i)
cin >> grape[i];
int dp[10001]{};
dp[1] = grape[1];
dp[2] = grape[1] + grape[2];
for (int i = 3; i <= n; ++i)
dp[i] = max(dp[i - 1], max(dp[i - 2], dp[i - 3] + grape[i - 1]) + grape[i]);
cout << dp[n];
}
λ¬Έμ : LIS(μ΅μ₯ μ¦κ° λΆλΆ μμ΄)
https://www.acmicpc.net/problem/11053
#include <iostream>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N, ans = 0;
cin >> N;
int A[1010]{}, dp[1010]{};
for (int i = 1; i <= N; i++)
cin >> A[i];
for (int i = 1; i <= N; i++) {
for (int j = 1; j < i; j++)
if (A[i] > A[j] && dp[i] < dp[j])
dp[i] = dp[j];
dp[i]++;
if (ans < dp[i])
ans = dp[i];
}
cout << ans;
}
https://www.acmicpc.net/problem/2565
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int N;
cin >> N;
vector<pair<int, int>> poles;
int dp[100];
for (int i = 0; i < N; i++) {
int a, b;
cin >> a >> b;
poles.push_back({ a, b });
dp[i] = 1;
}
// a μ λ΄λμ μ κΉμ€ μμΉλ₯Ό κΈ°μ€μΌλ‘ μ λ ¬
sort(poles.begin(), poles.end());
// a μ λ΄λλ₯Ό κΈ°μ€μΌλ‘ μ κΉμ€μ μ λ ¬νμ λ
// b μ λ΄λλ μ κΉμ€ μμκ° μ λ ¬λμ΄μμ΄μΌ λμ΄ μν€μ§ μλλ€.
for (int i = 0; i < N; i++)
for (int j = 0; j < i; j++)
if (poles[i].second > poles[j].second)
dp[i] = max(dp[i], dp[j] + 1);
// b μ λ΄λμ λΆλΆμ¦κ°μμ΄μ λͺ¨λ μ λ ¬λ μνμ΄λ―λ‘
// μλ κΈΈμ΄μμ λΆλΆμ¦κ°μμ΄μ κΈΈμ΄λ₯Ό λΊλ€.
cout << N - *max_element(dp, dp + N);
}
λ¬Έμ : LCS(μ΅μ₯ κ³΅ν΅ λΆλΆ μμ΄)
https://www.acmicpc.net/problem/9251
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int dp[1001][1001];
int main()
{
string s1, s2;
cin >> s1 >> s2;
for (int i = 1; i <= s1.length(); i++)
for (int j = 1; j <= s2.length(); j++)
dp[i][j] = (s1[i - 1] == s2[j - 1]) ? dp[i - 1][j - 1] + 1 : max(dp[i][j - 1], dp[i - 1][j]);
cout << dp[s1.length()][s2.length()];
}
λ¬Έμ : λ μ
μ£Όμ΄μ§ μ©λμ μ΄κ³Όνμ§ μμΌλ©΄μ μ 체 μ΄λμ΄ μ΅λκ° λ μ μλλ‘ νλ λ¬Έμ μ΄λ€.
https://www.acmicpc.net/problem/12865
#include <iostream>
#include <algorithm>
using namespace std;
int dp[100001];
int main()
{
int n, k;
cin >> n >> k;
while (n--) {
int w, v;
cin >> w >> v;
for (int i = 0; i <= k - w; i++)
dp[i] = max(dp[i], dp[i + w] + v);
}
cout << *max_element(dp, dp + k);
}
https://www.acmicpc.net/problem/2293
#include <iostream>
using namespace std;
int main()
{
int n, k;
cin >> n >> k;
int dp[10001]{ 1 };
for (int i = 0; i < n; i++) {
int tmp;
cin >> tmp;
for (int j = tmp; j <= k; j++)
dp[j] += dp[j - tmp];
}
cout << dp[k];
}
https://www.acmicpc.net/problem/11052
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N;
cin >> N;
int card[1001], dp[1001]{};
for (int i = 1; i <= N; ++i)
cin >> card[i];
for (int i = 1; i <= N; i++)
for (int j = 1; j <= i; j++)
dp[i] = max(dp[i], dp[i - j] + card[j]);
cout << dp[N];
}
λ¬Έμ : μ΅μλΉμ© ꡬνκΈ°
https://www.acmicpc.net/problem/11066
#include <iostream>
#include <algorithm>
using namespace std;
int dp[501][501];
int sum[501];
int main()
{
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> sum[i];
sum[i] += sum[i - 1];
}
for (int i = 1; i <= n; ++i)
for (int start = 1; start + i <= n; ++start) {
int end = start + i;
dp[start][end] = 1e9;
for (int j = start; j < end; ++j)
dp[start][end] = min(dp[start][end], dp[start][j] + dp[j + 1][end] + sum[end] - sum[start - 1]);
}
cout << dp[1][n] << endl;
}
}
https://www.acmicpc.net/problem/11049
#include <iostream>
#include <algorithm>
using namespace std;
int dp[501][501];
int a[501][2];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i][0] >> a[i][1];
if (i > 1)
dp[i - 1][i] = a[i - 1][0] * a[i - 1][1] * a[i][1];
}
for (int i = 2; i <= n; i++) // νλ ¬μ΄ 3κ° μ΄μμΌ κ²½μ°
for (int start = 1; start + i <= n; start++) {
int end = start + i;
dp[start][end] = 1e9;
for (int j = start; j < end; j++)
dp[start][end] = min(dp[start][end], dp[start][j] + dp[j + 1][end] + a[start][0] * a[j][1] * a[end][1]);
}
cout << dp[1][n];
}
https://leetcode.com/problems/dungeon-game/
#include <vector>
#include <math.h>
using namespace std;
class Solution
{
public:
int dp[201][201]{};
int calculateMinimumHP(vector<vector<int>>& dungeon)
{
int m = dungeon.size();
int n = dungeon[0].size();
for (int i = m - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
if (i == m - 1 && j == n - 1)
dp[i][j] = max(1, 1 - dungeon[i][j]);
else if (i == m - 1)
dp[i][j] = max(1, dp[i][j + 1] - dungeon[i][j]);
else if (j == n - 1)
dp[i][j] = max(1, dp[i + 1][j] - dungeon[i][j]);
else
dp[i][j] = max(1, min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]);
}
}
return dp[0][0];
}
};
λ¬Έμ : DFS+DP
https://www.acmicpc.net/problem/1520
#include <iostream>
using namespace std;
int M, N;
int h[500][500], dp[500][500];
int dir[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
int f(int y, int x, int hei)
{
if (x < 0 || x >= N || y < 0 || y >= M || h[y][x] >= hei)
return 0;
else if (y == M - 1 && x == N - 1)
return 1;
else if (dp[y][x] >= 0)
return dp[y][x];
dp[y][x] = 0;
for (int i = 0; i < 4; i++)
dp[y][x] += f(y + dir[i][0], x + dir[i][1], h[y][x]);
return dp[y][x];
}
int main()
{
cin >> M >> N;
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++) {
cin >> h[i][j];
dp[i][j] = -1;
}
cout << f(0, 0, h[0][0] + 1);
}
λ¬Έμ : DFS+BFS+DP
https://leetcode.com/problems/word-ladder-ii/
#include <vector>
#include <map>
#include <queue>
#include <string>
using namespace std;
class Solution {
public:
vector<vector<string>> answers;
vector<string> answer;
bool check[500];
map<string, int> counts;
int minCount;
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
minCount = 0;
queue<pair<string, int>> q;
q.push({ beginWord, 0 });
while (!q.empty()) {
string word = q.front().first;
int cnt = q.front().second;
q.pop();
if (word == endWord) {
minCount = cnt;
break;
}
for (int i = 0; i < wordList.size(); i++)
{
if (check[i] || isNearWord(word, wordList[i]) == false)
continue;
check[i] = true;
q.push({ wordList[i], cnt + 1 });
}
}
memset(check, false, sizeof(check));
answer.push_back(beginWord);
dfs(beginWord, endWord, wordList, 0);
return answers;
}
bool dfs(string& curWord, string& endWord, vector<string>& wordList, int count) {
if (count == minCount) {
if (curWord != endWord)
return false;
else {
answers.push_back(answer);
return true;
}
}
else if (counts.find(curWord) != counts.end() && counts[curWord] <= count)
return false;
bool movable = false;
for (int i = 0; i < wordList.size(); i++) {
if (check[i] || isNearWord(curWord, wordList[i]) == false)
continue;
check[i] = true;
answer.push_back(wordList[i]);
if (dfs(wordList[i], endWord, wordList, count + 1))
movable = true;
answer.pop_back();
check[i] = false;
}
if (movable == false)
counts[curWord] = count;
return movable;
}
bool isNearWord(string& cur, string& next) {
int cnt = 0;
for (int i = 0; i < cur.size(); i++)
if (cur[i] != next[i])
cnt++;
return cnt == 1;
}
};
λ¬Έμ : left to right
https://leetcode.com/problems/candy/description/
#include <vector>
using namespace std;
class Solution {
public:
int candy(vector<int>& ratings) {
int n = ratings.size();
vector<int> candyCount(n, 1);
// left to right
for (int i = 1; i < n; ++i) {
if (ratings[i - 1] < ratings[i]) {
candyCount[i] = candyCount[i - 1] + 1;
}
}
// right to left
for (int i = n - 2; i >= 0; --i) {
if (ratings[i] > ratings[i + 1]) {
candyCount[i] = max(candyCount[i], candyCount[i + 1] + 1);
}
}
int answer = 0;
for (int i = 0; i < candyCount.size(); ++i)
answer += candyCount[i];
return answer;
}
};
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/
#include <vector>
#include <math.h>
using namespace std;
class Solution {
public:
int maxProfit(vector<int>& prices) {
int size = prices.size();
vector<int> leftProfit(size, 0);
vector<int> rightProfit(size, 0);
int minPrice = prices[0];
for (int i = 1; i < size; ++i) {
minPrice = min(prices[i], minPrice);
leftProfit[i] = max(leftProfit[i - 1], prices[i] - minPrice);
}
int maxPrice = prices[size - 1];
for (int i = size - 2; i >= 0; --i) {
maxPrice = max(prices[i], maxPrice);
rightProfit[i] = max(rightProfit[i + 1], maxPrice - prices[i]);
}
int answer = 0;
for (int i = 0; i < size; ++i)
answer = max(answer, leftProfit[i] + rightProfit[i]);
return answer;
}
};