算法提高--最长上升子序列一

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 }
原文地址:https://www.cnblogs.com/greenofyu/p/14961460.html