最长上升子序列
方法一:
- dp[i]表示为以i结尾的最长长度,那么if(a[j]<a[i])(j<i) dp[i] = max(dp[i],dp[j]+1);
- 对于最长不下降子序列,代码就改一个等号。
代码:复杂度O(n*n)
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
int const N = 1000 + 10;
int n;
int dp[N],val[N];
int main(){
while(~scanf("%d",&n)){
for(int i=0;i<n;i++) scanf("%d",&val[i]);
int ans = 0;
for(int i=0;i<n;i++){
dp[i] = 1; //这里别忘记初始化
for(int j=0;j<i;j++)
if(val[i] > val[j]) //如果有等号,那么就是最长不下降子序列
dp[i] = max(dp[i],dp[j]+1);
ans = max(ans,dp[i]); //每次找最大值,不能直接输出dp[n-1]
}
printf("%d\n",ans);
}
}
方法二:
代码:(n*logn)
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
int const N = 1000 + 10;
int const inf = 0x7f7f7f7f;
int n,tmp;
int v[N];
int main(){
while(~scanf("%d",&n)){
fill(v,v+n,inf);
for(int i=0;i<n;i++){
scanf("%d",&tmp);
*lower_bound(v,v+n,tmp) = tmp; //upper_bound()是求最长不下降子序列
}
printf("%d\n",lower_bound(v,v+n,inf)-v);
}
return 0;
}
HDU1087:
题解:一道变形题目,求上升子序列最大和。O(n*n)的做法。
代码:
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
int const N = 1000 + 10;
int n,val[N];
ll dp[N]; //dp[i]记录长度为i的最长上升子序列前缀和
int main(){
while(~scanf("%d",&n) && n){
for(int i=0;i<n;i++) scanf("%d",&val[i]);
ll ans = 0;
for(int i=0;i<n;i++){
dp[i] = 1ll*val[i]; //这里别忘记初始化
for(int j=0;j<i;j++)
if(val[i] > val[j])
dp[i] = max(dp[i],dp[j]+val[i]);
ans = max(ans,dp[i]);
}
printf("%lld\n",ans);
}
}
HDU1950&&HDU1025
题解:裸题LIS
代码:hdu1950
#include <bits/stdc++.h>
using namespace std;
int const N = 40000 + 10;
int const inf = 0x7f7f7f7f;
int dp[N];
int main(){
int T;
scanf("%d",&T);
while(T--){
int p;
scanf("%d",&p);
fill(dp,dp+p,inf);
for(int i=0;i<p;i++){
int tmp; scanf("%d",&tmp);
*lower_bound(dp,dp+p,tmp) = tmp;
}
printf("%d\n",lower_bound(dp,dp+p,inf)-dp);
}
}
代码:HDU1025(注意road和roads的区别。。。)
#include <bits/stdc++.h>
using namespace std;
int const N = 500000 + 10;
int const inf = 0x7f7f7f7f;
int dp[N],n;
int mp[N];
int main(){
int caser = 0;
while(~scanf("%d",&n)){
printf("Case %d:\n",++caser);
fill(dp,dp+n,inf);
for(int i=0;i<n;i++){
int t1,t2; scanf("%d%d",&t1,&t2);
mp[t1] = t2;
}
for(int i=1;i<=n;i++)
*lower_bound(dp,dp+n,mp[i]) = mp[i];
int len = lower_bound(dp,dp+n,inf)-dp;
if(len == 1) printf("My king, at most %d road can be built.\n\n",len);
else printf("My king, at most %d roads can be built.\n\n",len);
}
}