kuangbin帶你飛:點擊進入新世界node
原題連接:傳送門ios
原題連接:傳送門c++
思路: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; } } } }
原題連接:傳送門promise
解析:對於所給的磚塊能夠有6種組合(即:長寬高打亂)因此最終的 $ index = 6 * n$spa
#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; } }
HDU - 1074.net
解析:code
先大體說說狀態壓縮,假設有三門做業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; }
解析:注意題目是嚴格上升子序列並非連續上升子序列(致使我寫錯了轉移方程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模板題:最少攔截系統:傳送門
每種硬幣的數量都不限制,所以是個徹底揹包。初始化dp數組時需注意,由於求的最小,且題目的意思是剛好裝滿,因此dp數組初始化爲INF,但dp[0] = 0,意爲此時只有容量爲0 的揹包能夠在什麼也不裝且價值爲0 的狀況下被「剛好裝滿」,其它容量的揹包均沒有合法的解,屬於未定義的狀態(揹包九講)
#include<bits/stdc++.h> using namespace std; const int N = 10010; const int inf = 0x3f3f3f3f; int dp[N], v[N], w[N]; int n, t, e, f; int main() { //freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> t; while (t--) { cin >> e >> f; int W = f - e; cin >> n; for (int i = 1; i <= n; ++i)cin >> v[i] >> w[i]; memset(dp, 0x3f, sizeof dp); dp[0] = 0; for (int i = 1; i <= n; ++i) for (int j = w[i]; j <= W; ++j) dp[j] = min(dp[j], dp[j - w[i]] + v[i]); if(dp[W] == inf )printf("This is impossible.\n"); else printf("The minimum amount of money in the piggy-bank is %d.\n", dp[W]); } }
思路:
若是把時間軸當作行數,每一個點在這個時間上得到的餅數當作列數,那麼a[i][j]表示在時間爲i時j點得到的餅,若是把圖畫出來就能夠發現這實際上是一道數塔題。
由於要處理相鄰兩邊,下標爲0的時候很差處理,因此把位置+1;
既然是數塔題,那麼顯而易見:
$ dp[i][j] = max({dp[i + 1][j - 1],dp[i + 1][j], dp[i + 1][j + 1]}) + a[i][j];$
這道題再升級一下就是加上高度的。POJ 1661Help Jimmy(逆向DP Or 記憶化搜索 Or 最短路徑)
#include<bits/stdc++.h> using namespace std; #define ms(a,b) memset(a,b,sizeof a); const int maxn = 1e5 + 50; int t, x, y; int a[maxn][15], dp[maxn][15]; int main() { //freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); while (cin >> t && t) { ms(dp, 0); ms(a, 0); int e = 0; for (int i = 0; i < t; ++i) { cin >> x >> y; a[y][++x]++; e = max(e, y); } for (int i = e; i >= 0; i--) for (int j = 1; j <= 11; j++) dp[i][j] = max({dp[i + 1][j - 1],dp[i + 1][j], dp[i + 1][j + 1]}) + a[i][j]; cout << dp[0][6] << endl; } }
思路:
#include<bits/stdc++.h> using namespace std; const int maxn = 2010; int a[maxn], b[maxn], dp[maxn]; int n, m, r, t = 0; int main() { //freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); while (cin>>t) { while (t--) { cin >> n; for (int i = 1; i <= n; ++i)cin >> a[i]; for (int i = 2; i <= n; ++i)cin >> b[i]; dp[1] = a[1]; for (int i = 2; i <= n; ++i)dp[i] = min(dp[i - 1] + a[i], dp[i - 2] + b[i]); int h = 8, mi = 0, sec = 0; sec += dp[n]; mi += sec / 60 % 60; h += sec / 3600; sec %= 60; printf("%02d:%02d:%02d ", h, mi, sec); if (h >= 12) printf("pm\n"); else printf("am\n"); } } }
#include<bits/stdc++.h> using namespace std; struct Mouse { int id; int speed; int weight; int pre; int dp; } mouse[10010]; int cmp(Mouse a, Mouse b) { if (a.weight == b.weight) { return a.speed > b.speed; } return a.weight < b.weight; } int dfs(int p) { //printf("@%d %d\n",p,mouse[p].pre); if (p == -1) return 0; dfs(mouse[p].pre); printf("%d\n", mouse[p].id); return 0; } int main() { int i = 0; while (~scanf("%d%d", &mouse[i].weight, &mouse[i].speed)) { mouse[i].id = i + 1; mouse[i].pre = -1; mouse[i].dp = 1; i++; } sort(mouse, mouse + i, cmp); int n = i; mouse[0].dp = 1; int ans = 1; int p = 0; for (int i = 1; i < n; i++) { for (int j = 0; j < i; j++) { if (mouse[i].weight > mouse[j].weight && mouse[i].speed < mouse[j].speed) { if (mouse[j].dp + 1 > mouse[i].dp) { mouse[i].dp = mouse[j].dp + 1; mouse[i].pre = j; } } } if (mouse[i].dp > ans) { ans = mouse[i].dp; p = i; } } /* for(int i=0;i<n;i++) { printf("id:%d w:%d s:%d pre:%d dp:%d\n",mouse[i].id,mouse[i].weight,mouse[i].speed,mouse[i].pre,mouse[i].dp); }*/ printf("%d\n", ans); dfs(p); return 0; }
思路:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3 + 10; int dp[maxn][maxn], a[maxn][maxn]; int nx[] = { 0,1,0,-1 }; int ny[] = { 1,0,-1,0 }; int n, m, r, t = 1; int dfs(int x, int y) { if (dp[x][y]) return dp[x][y]; int mx = 0; for (int i = 1; i <= m; ++i) { for (int j = 0; j < 4; ++j) { int xx = x + nx[j] * i, yy = y + ny[j] * i; if (a[x][y] < a[xx][yy] && xx>0 && yy > 0 && xx <= n && yy <= n) mx = max(dfs(xx, yy), mx); } } return dp[x][y] = a[x][y] + mx; } int main() { //freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); while (cin >> n >> m && n != -1 &&m != -1) { for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) cin >> a[i][j]; memset(dp, 0, sizeof dp); cout << dfs(1, 1) << endl; } }
思路:
#include<bits/stdc++.h> using namespace std; #define ms(a,b) memset(a,b,sizeof a); const int N = 1010; char a[N][N]; int dp[N][N]; int n; int main() { freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); while (cin >> n && n) { ms(dp, 0); int ans = 1; for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)cin >> a[i][j]; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { dp[i][j] = 1; int x = i, y = j; while (a[i][y] == a[x][j])x--, y++; if(a[i][j + 1] == a[i - 1][j]) dp[i][j] = min(dp[i - 1][j + 1], i - x - 1) + 1; ans = max(ans, dp[i][j]); } cout << ans << endl; } }