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; } }