[kuangbin帶你飛]專題十二 基礎DP1 題解+總結
阿新 • • 發佈:2020-07-17
kuangbin帶你飛:點選進入新世界
文章目錄
目錄
1.Max Sum Plus Plus
原題連結:傳送門
2.Ignatius and the Princess IV
原題連結:傳送門
思路:hash儲存(感覺和dp沒啥關係啊。。)
#include<bits/stdc++.h> using namespace std; map<int, int>mp; int n, t; int main() { freopen("in.txt", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); while (cin >> n) { mp.clear(); for (int i = 0; i < n; ++i) { cin >> t; mp[t]++; } for (auto &p : mp) { if (p.second >= (n + 1) / 2) { cout << p.first << endl; break; } } } }
3.Monkey and Banana
原題連結:傳送門
解析:對於所給的磚塊可以有6種組合(即:長寬高打亂)所以最終的 $ index = 6 * n$
#include<bits/stdc++.h> using namespace std; const int maxn = 1000; struct node { int l, r, w;//長寬高 }a[maxn]; int n, r, w, l; bool cmp(node &a, node &b) { if (a.l == b.l)return a.r < b.r; return a.l < b.l; } int dp[maxn]; int main() { freopen("in.txt", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); int Case = 1; while (cin >> n && n) { int index = 1; for (int i = 0; i < n; ++i) { cin >> l >> r >> w; a[index].l = l, a[index].r = r, a[index++].w = w; a[index].l = r, a[index].r = l, a[index++].w = w; a[index].l = w, a[index].r = r, a[index++].w = l; a[index].l = l, a[index].r = w, a[index++].w = r; a[index].l = r, a[index].r = w, a[index++].w = l; a[index].l = w, a[index].r = l, a[index++].w = r; } sort(a + 1, a + index + 1,cmp);//根據長寬排序 memset(dp, 0,sizeof dp); int ans = 0; for(int i = 1;i <= index;++i) for (int j = 1; j <= index; ++j) { if (a[i].r < a[j].r && a[i].l < a[j].l) dp[j] = max(dp[j], dp[i] + a[j].w), ans = max(ans, dp[j]); } cout << "Case " << Case++ << ": maximum height = " << ans << endl; } }
4.Doing Homework
解析:
先大致說說狀態壓縮,假設有三門作業a,b,c
那麼,abc都做完即111,111可由101,110,011任意一個來得到。而101可以從100或者001來得到,這就是狀態壓縮dp的一個基本的狀態轉移。
#include<bits/stdc++.h> using namespace std; const int N = 16; struct Node { char str[109]; int want, need; }node[N]; struct DP { int now, sum, next, pos; }dp[1 << N]; void put_ans(int x) { if (dp[x].next != -1) { put_ans(dp[x].next); printf("%s\n", node[dp[x].pos].str); } } int main() { freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while (T--) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%s%d%d", node[i].str, &node[i].want, &node[i].need); dp[0].now = dp[0].sum = 0; dp[0].next = dp[0].pos = -1; int m = (1 << n) - 1; for (int i = 1; i <= m; i++) { dp[i].sum = 0x3f3f3f3f; for (int j = 0; j < n; j++) { if ((1 << j) & i) { int k = i - (1 << j); int v = dp[k].now + node[j].need - node[j].want; v = max(v, 0); if (dp[i].sum >= dp[k].sum + v) { dp[i].sum = dp[k].sum + v; dp[i].now = dp[k].now + node[j].need; dp[i].next = k; dp[i].pos = j; } } } } printf("%d\n", dp[m].sum); put_ans(m); } return 0; }
5.Super Jumping! Jumping! Jumping!
解析:注意題目是嚴格上升子序列並不是連續上升子序列(導致我寫錯了轉移方程2333)
#include<bits/stdc++.h>
using namespace std;
#define ms(a,b) (a,b,sizeof a)
const int maxn = 1e3 + 10;
int dp[maxn], a[maxn];
int n;
int main() {
freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false); cin.tie(0);
while (cin >> n && n) {
ms(dp, 0);
for (int i = 0; i < n; ++i)
cin >> a[i], dp[i] = a[i];
int ans = 0;
for (int i = 0; i < n; ++i)
{
for (int j = i + 1; j < n; ++j)
{
if (a[j] > a[i])
dp[j] = max(dp[j], dp[i] + a[j]);
}
ans = max(ans, dp[i]);
}
cout << ans << endl;
}
}
同樣是LIS模板題:最少攔截系統:傳送門
Piggy-Bank