【DP经典问题】
来源:互联网 发布:centos www服务器配置 编辑:程序博客网 时间:2024/06/06 02:39
最大连续和:
O(n) 算法: f[n] = max(f[n-1]+a[n], a[n])
O(nlogn) 算法:分治算法,算法竞赛入门经典有介绍
hackerrank给了一个 k-dane 算法:http://blog.csdn.net/joylnwang/article/details/6859677
最大子序列和(不要求连续):f[i]表示 1-i 最大子序列和,用d[i]表示最大子序列的结束位置。。
LIS问题:
nlogn算法: d[i] 保存长度为i的上升子序列的最后一个元素,维护d[i]使得d[i]总是最小。
可以这样理解,对于相同长度的IS,最后一个元素较小的子序列增长的“潜力”较大。
如果需要输出LIS,则 d[i] 保存的是下标,pa[i]保存上一个元素下标。代码见LCS问题。
// poj 2533#include<iostream>#include<cstdio>#include<cstdlib>#include<map>#include<algorithm>#include<vector>#include<queue>#include<cstring>#include<set>#include<list>using namespace std;const int maxn = 1000000;const int inf = 0x7fffffff;int T, n;int a[maxn+5];int d[maxn+5];int main() {#if 0 freopen("input.in", "r", stdin);#endif scanf("%d",&n); if (n == 0) {printf("0");return 0;} for (int i=1;i<=n;++i) scanf("%d", &a[i]); for (int i=1;i<=n;++i) d[i] = inf; d[0] = 0; d[1] = a[1]; for (int i=2;i<=n;++i) { int *p = lower_bound(d+1, d+n, a[i]); if (*p > a[i]) *p = a[i]; } int ans = 1; for (int i=n;i>=1;--i) if (d[i] != inf) { ans = i; break; } //for (int i=1;i<=n;++i) cout << d[i] << ' ';cout << endl; printf("%d\n", ans); return 0;}
LCS问题:
nlogn算法:http://blog.csdn.net/non_cease/article/details/6918848
将LCS转换成LIS来解决,思想也非常容易理解。
#include <cmath>#include <cstdio>#include <vector>#include <iostream>#include <algorithm>#include <map>using namespace std;#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))#define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i))const int inf = 0x7fffffff;const int maxn = (int)(1e5);int n, m, len;int a[maxn+5];int b[maxn+5];int d[maxn+5];int pa[maxn+5];vector<int> sav[maxn+5];vector<int> arr; // array to get LISmap<int, int> ha;bool cmp(int lhs, int rhs) { if (lhs == inf) return false; if (rhs == inf) return true; return arr[lhs] < arr[rhs];}int main() {#if 1 freopen("input.in", "r", stdin);#endif cin >> n >> m; rep(i, 0, n-1) cin >> a[i]; rep(i, 0, m-1) cin >> b[i]; // map element in a [1-1e9] to [1-1e6], hash_value = position where the element firstly appearanced // hash_value = ha[origin_value], origin_value = a[hash_value] rep(i, 0, n-1) { if (ha.count(a[i]) == 0) { ha[a[i]] = i; } } // for every distinct element in a, find its appearance in b urep(i, m-1, 0) { if (ha.count(b[i])) { sav[ha[b[i]]].push_back(i); } } rep(i, 0, n-1) { if (ha.count(a[i])) { int id = ha[a[i]]; int sz = sav[id].size(); rep(j, 0, sz-1) arr.push_back(sav[id][j]); } } len = min(n, m); rep(i, 0, len) d[i] = inf; d[1] = 0; d[0] = -1; pa[0] = -1; int sz = arr.size(); rep(k, 0, sz-2) cout << arr[k] << " ";cout << arr[sz-1] << endl; rep(k, 1, sz-1) { int *p = lower_bound(d+1, d+len, k, cmp); if (cmp(k, *p)) { pa[k] = *(p-1); *p = k; } } int idx; for(idx=len;idx>=1;--idx) if (d[idx] != inf) break; vector<int> ans; int cur = d[idx]; //cout << "length: " << idx << endl; while (cur != -1) { ans.push_back(b[arr[cur]]); cur = pa[cur]; } sz = ans.size(); rep(i, 0, sz-2) cout << ans[sz-1-i] << " ";cout << ans[0] << endl; return 0;}
0 0
- 邮局--dp经典问题
- 【DP经典问题】WordBreak
- 树形DP经典问题
- 经典DP问题
- 【DP经典问题】
- 硬币问题 经典dp
- dp经典问题
- 硬币问题(经典dp)
- poj1157(花店问题+经典DP)
- 经典DP题目-滑雪问题
- POJ1157 花店问题经典DP
- 环形石子合并问题 - 经典DP问题
- ZOJ1733 POJ1458 Common Subsequence,经典DP问题
- hoj 整数划分问题 经典dp
- 入门经典 DP 0-1背包问题
- 经典问题石子合并(环形)DP
- 最长公共子序列问题 经典DP
- 经典DP 多重部分和问题
- 黑马程序员———字符串和字符串缓冲区
- java 文件操作之byte数组间的转换
- iOS coreText 图文混排
- Bundle类的作用
- PlaySound与CFileDialog
- 【DP经典问题】
- PhotoShop算法实现--直方图(十)
- POJ2353——Ministry
- 黑马程序员———基本数据类型对象包装类
- 机房收费系统合作版——VS2013自带报表
- HIVE 0.14.0安装
- 百灵面试
- 杭电1233还是畅通工程
- An introduction to Linux Virtual Address Space Layout