Dynamic Programming I
Introduction
Knapsack
Paths on Grids
簡介
1. 前綴和
2. 狀態 / 轉移式
Introduction
前綴和
Prefix Sum
Introduction
Code
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n = 8;
vector<int> a = {0, 3, 3, 5, 2, 2, 4, 8, 6};
vector<int> pre(n + 1);
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + a[i];
}
// index = 5 前綴和查詢
cout << pre[5] << endl;
// 區間 [2, 5] 和查詢 = (5 前綴和) - (1 前綴和)
cout << pre[5] - pre[1] << endl;
}
背包問題
1. Minimizing Coins
2. Coin Combinations
3. Money Sums
Knapsack
題目
遞迴
Recursive formulation
Knapsack
Code
int solve(int x) {
if (x < 0) return INF;
if (x == 0) return 0;
int best = INF;
for (int c : coins) {
best = min(best, solve(x - c) + 1);
}
return best;
}
bool ready[N]; // 是否被計算過
int value[N]; // 被計算過的值
Knapsack
Code II
int solve(int x) {
if (x < 0) return INF;
if (x == 0) return 0;
if (ready[x]) return value[x];
int best = INF;
for (int c : coins) {
best = min(best, solve(x - c) + 1);
}
value[x] = best;
ready[x] = true;
return best;
}
value[0] = 0;
for (int x = 1; x <= n; x++) {
value[x] = INF;
for (int c : coins) {
if (x - c >= 0) {
value[x] = min(value[x], value[x - c] + 1);
}
}
}
Knapsack
AC Code
#include <iostream>
#include <vector>
using namespace std;
const int INF = 1e6 + 1;
int main() {
int n, x;
cin >> n >> x;
vector<int> coins(n);
for (int i = 0; i < n; i++) {
cin >> coins[i];
}
vector<int> dp(x + 1, INF);
dp[0] = 0;
for (int i = 1; i <= x; i++) {
for (int c : coins) {
if (i - c >= 0) {
dp[i] = min(dp[i], dp[i - c] + 1);
}
}
}
cout << (dp[x] == INF ? -1 : dp[x]) << '\n';
}
Knapsack
輸出最佳解
Constructing a solution
int first[N]; // 對於和為 i, 選擇硬幣 first[i] 為最佳解
value[0] = 0;
for (int x = 1; x <= n; x++) {
value[x] = INF;
for (int c : coins) {
if (x - c >= 0 && value[x - c] + 1 < value[x]) {
value[x] = value[x - c] + 1;
first[x] = c;
}
}
}
while (n > 0) {
cout << first[n] << endl;
n -= first[n];
}
Knapsack
題目
Knapsack
Code
count[0] = 1;
for (int x = 1; x <= n; x++) {
for (int c : coins) {
if (x - c >= 0) {
count[x] += count[x - c];
}
}
}
count[x] += count[x - c];
count[x] %= mod;
Knapsack
AC Code
#include <iostream>
#include <vector>
using namespace std;
const int mod = 1e9 + 7;
int main() {
int n, x;
cin >> n >> x;
vector<int> coins(n);
for (int i = 0; i < n; i++) {
cin >> coins[i];
}
vector<int> dp(x + 1);
dp[0] = 1;
for (int i = 1; i <= x; i++) {
for (int c : coins) {
if (i - c >= 0) {
dp[i] = (dp[i] + dp[i - c]) % mod;
}
}
}
cout << dp[x] << '\n';
}
Knapsack
題目
vector<bool> dp(x + 1);
dp[0] = true;
for (int i = 0; i <= x; i++) {
for (int c : coins) {
if (dp[i]) dp[i + c] = true;
}
}
Knapsack
Solution
vector<bool> dp(x + 1);
dp[0] = true;
for (int c : coins) {
for (int i = x; i >= 0; i--) {
if (dp[i]) dp[i + c] = true;
}
}
Knapsack
AC Code
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> coins(n);
int sum = 0;
for (int i = 0; i < n; i++) {
cin >> coins[i];
sum += coins[i];
}
vector<bool> dp(sum + 1);
dp[0] = true;
for (int i = 0; i < n; i++) {
for (int j = sum; j >= 0; j--) {
if (dp[j]) dp[j + coins[i]] = true;
}
}
vector<int> ans;
for (int i = 1; i <= sum; i++) {
if (dp[i]) ans.push_back(i);
}
cout << ans.size() << '\n';
for (int a : ans) cout << a << ' ';
cout << '\n';
}
Knapsack
題單
Knapsack
路徑
1. Grid Paths
2. Edit Distance
Paths on Grids
題目
AC Code
#include <iostream>
#include <vector>
using namespace std;
const int mod = 1e9 + 7;
int main() {
int n;
cin >> n;
vector<vector<int>> dp(n + 1, vector<int>(n + 1));
dp[0][1] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
char c;
cin >> c;
if (c == '.') {
dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % mod;
}
}
}
cout << dp[n][n] << '\n';
}
Paths on Grids
題目
Paths on Grids
AC Code
#include <iostream>
#include <string>
using namespace std;
int main() {
string a, b;
cin >> a >> b;
int n = a.length();
int m = b.length();
int dp[n + 1][m + 1];
dp[0][0] = 0;
for (int j = 1; j <= m; j++) dp[0][j] = j;
for (int i = 1; i <= n; i++) {
dp[i][0] = i;
for (int j = 1; j <= m; j++) {
dp[i][j] = min(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1),
dp[i - 1][j - 1] + (a[i - 1] != b[j - 1]));
}
}
cout << dp[n][m] << '\n';
}
Paths on Grids
題單
Paths on Grids