https://www.acwing.com/problem/content/897/
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int N=1010; 6 int w[N],f[N]; 7 int main() 8 { 9 int n; 10 cin>>n; 11 for(int i=1;i<=n;i++) cin>>w[i]; 12 for(int i=1;i<=n;i++){ 13 f[i]=1; 14 for(int j=1;j<i;j++){ 15 if(w[i]>w[j]) 16 f[i]=max(f[i],f[j]+1); 17 } 18 } 19 int res=-1; 20 for(int i=1;i<=n;i++) res=max(res,f[i]); 21 cout<<res; 22 return 0; 23 }
https://www.acwing.com/problem/content/1019/
扩展1:最长上升子序列扩展为双向,从左到右或者从右到左。
在反着做一遍最长上升子序列即可。
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int N=110; 6 int w[N],f[N],g[N];//f[i]表示1~i且包含i的最长上升子序列的长度。 7 //g[i]表示n-1~i且包含i的最长上升子序列的长度。 8 int main() 9 { 10 int T; 11 cin>>T; 12 while(T--){ 13 int n; 14 cin>>n; 15 for(int i=0;i<n;i++) cin>>w[i]; 16 int res=0; 17 for(int i=0;i<n;i++){ 18 f[i]=1; 19 for(int j=0;j<i;j++){ 20 if(w[i]>w[j]) 21 f[i]=max(f[i],f[j]+1); 22 } 23 res=max(res,f[i]); 24 } 25 for(int i=n-1;i>=0;i--){ 26 g[i]=1; 27 for(int j=n-1;j>i;j--){ 28 if(w[i]>w[j]) 29 g[i]=max(g[i],g[j]+1); 30 } 31 res=max(res,g[i]); 32 } 33 cout<<res<<endl; 34 } 35 return 0; 36 }
https://www.acwing.com/problem/content/1016/
1、按顺序浏览景点
2、任意两相邻景点高度不同
3、一旦开始下山就不能在往上
也即要找到一个子序列使得高度呈现以上的形态。
类比上一怪盗基德的题,我们可以枚举最高点。
最高点作为左边和右边上升子序列的最高点。
求出以这个点 i 结尾的从左开始的最长上升子序列和从右开始的最长上升子序列,遍历一遍即可。
【注】最高点加了两遍,所以要减一
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int N=1010; 6 int w[N],f[N],g[N];//f[i]表示1~i且包含i的最长上升子序列的长度。 7 //g[i]表示n-1~i且包含i的最长上升子序列的长度。 8 int main() 9 { 10 int n; 11 cin>>n; 12 for(int i=0;i<n;i++) cin>>w[i]; 13 for(int i=0;i<n;i++){ 14 f[i]=1; 15 for(int j=0;j<i;j++){ 16 if(w[i]>w[j]) 17 f[i]=max(f[i],f[j]+1); 18 } 19 } 20 for(int i=n-1;i>=0;i--){ 21 g[i]=1; 22 for(int j=n-1;j>i;j--){ 23 if(w[i]>w[j]) 24 g[i]=max(g[i],g[j]+1); 25 } 26 } 27 int res=0; 28 for(int i=0;i<n;i++) res=max(res,f[i]+g[i]-1); 29 cout<<res<<endl; 30 return 0; 31 }
https://www.acwing.com/problem/content/484/
2004 NOIP提高组 合唱队形
问题同登山,不过问的是最少出列几个同学能够使得队形成为上升再下降的形状。
出来的最少==留下的最多。
cout<<n-res即可。
https://www.acwing.com/problem/content/1014/
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 typedef pair<int,int> PII; 6 const int N=5010; 7 PII w[N]; 8 int f[N]; 9 int main() 10 { 11 int n; 12 cin>>n; 13 for(int i=0;i<n;i++) cin>>w[i].first>>w[i].second; 14 sort(w,w+n); 15 int res=0; 16 for(int i=0;i<n;i++){ 17 f[i]=1; 18 for(int j=0;j<i;j++){ 19 if(w[i].second>w[j].second) 20 f[i]=max(f[i],f[j]+1); 21 } 22 res=max(res,f[i]); 23 } 24 cout<<res; 25 return 0; 26 }
https://www.acwing.com/problem/content/1018/
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int N=1010; 6 int w[N],f[N]; 7 int main() 8 { 9 int n; 10 cin>>n; 11 for(int i=0;i<n;i++) cin>>w[i]; 12 int res=0; 13 for(int i=0;i<n;i++){ 14 f[i]=w[i]; 15 for(int j=0;j<i;j++){ 16 if(w[i]>w[j]) 17 f[i]=max(f[i],f[j]+w[i]); 18 } 19 res=max(res,f[i]); 20 } 21 cout<<res; 22 return 0; 23 }