动态规划--最长上升子序列LIS
来源:互联网 发布:淘宝店铺卖家等级 编辑:程序博客网 时间:2024/06/05 13:30
1.记录以Ak结尾的最长增长子序列的长度 O(n^2)
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn =1005;
int num[maxn];
int maxlen[maxn];
int main()
{
int n;
cin >> n;
for (int i =1; i <= n; i ++) {
scanf("%d",&num[i]);
}
fill(maxlen + 1, maxlen + n +1,1);
for (int i =2; i <= n; i ++) {
for (int j = i -1; j >0; j --) {
if (num[i] > num[j]) {
maxlen[i] = max(maxlen[i],maxlen[j] + 1);//maxlen[k]记录以Ak结尾的最长增长子序列的长度
}//于是,每次寻找,在Ak左边,并且,数字比Ak小的数Aj,用maxlen[j] + 1不断更新
}
}
cout << *max_element(maxlen + 1, maxlen + n +1) << endl;
return0;
}
2.O(n^2)
根据图得
每个端点可以选择向后面比他大的点走
而往哪个点走,取决于往哪走可以得到最大值lis
对于最后一个点来说,在他前面比他小的点都可以到达他
而从lis,的起点到终点,中间经过更多点,则增长子序列更长
位置i,dp[i]表示lis长度
得到1.递推 dp[i] = max(dp[i],dp[j] +1)对每个点i,在他前面的点j,如果小于他,那么最大值,可能是,lis没有j点->dp[i],或者,经过j点->dp[j] + 1
2.边界初始值全为1,一个数就是他的增长子序列。
代码同上,i = 2 to n,保证i之前的j的maxlen都是有效的(因为i要用到他所有前面的j的maxlen)
3.二分查找 O(nlgn)
用b[k]存上升子序列长度为k时,子序列结尾的最小值。
若i < j,b[i] < b[j]
若num[i] > b[k],b[k + 1] = num[i],k ++
若num[i] < b[k],在b[1]..b[k - 1]中寻找大于num[i]的最小值,即第一个大于num[i]的位置pos,b[pos] = min(b[pos],num[i]),maxlen[i] = pos
二分查找,所以是logn
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespacestd;
const int maxn =500005;
int num[maxn];
int b[maxn];
int maxlen[maxn];
int solve(int n)
{
int k =1;
b[1] =num[1];
maxlen[1] =1;
for (int i =2; i <= n; i ++) {
if (num[i] >=b[k]) {
maxlen[i] = k +1;
b[k +1] =num[i];
k ++;
}
else{
int pos =lower_bound(b +1,b + k,num[i]) -b;//在b[1]..b[k - 1]里找
maxlen[i] = pos;
b[pos] =min(b[pos],num[i]);
}
}
return k;
}
void output(int res)
{
if (res ==1) {
printf("My king, at most 1 road can be built.\n");
}
else printf("My king, at most %d roads can be built.\n",res);
}
int main()
{
int n,p,r;
int ce =0;
while (scanf("%d",&n) !=EOF) {
memset(num,0,sizeof(num));
memset(maxlen,0,sizeof(maxlen));
memset(b,0,sizeof(b));
for (int i =0; i < n; i ++) {
scanf("%d%d",&p,&r);
num[p] = r;
}
printf("Case %d:\n",++ce);
output(solve(n));
printf("\n");
}
return0;
}
记录路径 O(n^2)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespacestd;
const int maxn =1005;
struct mouse{
int w,s,id;
booloperator < (constmouse &a) const
{
if(w < a.w)returntrue;
elseif(w == a.w &&s > a.s)returntrue;
elsereturnfalse;
}
}mouse[maxn];//weigh speed
int maxlen[maxn];
int pre[maxn];
void lds(int cnt)
{
for (int i =1; i <= cnt; i ++) {
pre[i] =0;
maxlen[i] =1;
}
for (int i =2; i <= cnt; i ++) {
for (int j =1; j < i; j ++) {
if (mouse[i].w >mouse[j].w &&mouse[i].s <mouse[j].s &&maxlen[i] < maxlen[j] +1) {//要求w严格上升,i在j之后不一定就大
pre[i] = j;
maxlen[i] =1 +maxlen[j];
}
}
}
int len =1,num =1;
for (int i =1; i <= cnt; i ++) {
if (maxlen[i] > len) {
num = i;
len = maxlen[i];
}
}
vector<int> v;
v.push_back(num);
for (int i = len -1; i >0; i --) {
num = pre[num];
v.push_back(num);
}
cout << len <<endl ;
for (int i = len -1; i >=0; i --) {
cout <<mouse[v[i]].id <<endl;
}
}
int main()
{
int cnt =1;
while (cin >>mouse[cnt].w >>mouse[cnt].s) {
mouse[cnt].id = cnt;
cnt ++;
}
cnt --;
sort(mouse +1,mouse +1 + cnt);
//求mouse_s里的严格最大下降子序列
lds(cnt);
return0;
}
- 动态规划-最长上升子序列LIS
- 动态规划-最长上升子序列【LIS】
- 动态规划 LIS最长上升子序列
- 动态规划--最长上升子序列LIS
- 动态规划-最长上升子序列(LIS)
- 【动态规划】最长上升子序列(LIS)
- 动态规划_最长上升子序列LIS
- 动态规划——最长上升子序列问题(LIS)
- 动态规划 最长上升子序列(LIS)
- 【转载】动态规划--最长上升子序列(LIS)
- 动态规划7:最长上升子序列LIS
- 动态规划DP_最长上升子序列LIS
- 动态规划 - 最长递增子序列LIS
- 最长递增子序列(LIS)-动态规划
- 动态规划:最长上升子序列
- 动态规划求最长上升子序列
- 【算法】动态规划 最长上升子序列
- 动态规划:最长上升子序列
- git版本管理
- Django的是如何工作的
- Linux--线程控制
- CentOS7搭建FastDFS V5.11分布式文件系统及Java整合详细过程(三)
- 4.2.1--简单的广搜--Asteroids!
- 动态规划--最长上升子序列LIS
- 日语语法(三):动词
- CF
- “玲珑杯”线上赛 Round #15 咸鱼商店(二分搜索+01背包)
- React-Native的微信SDK辅助包,支持微信登录、微信分享、微信支付
- python学习笔记(函数)
- VS2010版最常用的快捷键和其他快捷键
- 使用Fragment 写 微信类似的页面切换
- React Native 接入微博、微信、QQ 登录功能