1996:登山

1996:登山

传送门
1、此题坑点在于先上山后要下山

2、最后求上升子序列+下降子序列的最长长度类似 1481:Maximum sum这题

3、要注意的是
写双重循环时内重循环 j++ 不要 写成外层循环变量 i++
这种错误在写这题出现了两次,陷入死循环不得出来

在此题中用这样 求下降子序列长度的方式 行不通,因为最终求的是
从左到右的最长上升子序列+接着的最长下降子序列,
如果这种循环方式确实能求出最长下降子序列,但是dp1[i]表示的就是从下标0到i这一段的最长下降子序列
而按题意要求的应该是
从下标i到n-1这一段的最长下降子序列
下面这个例子就过不去,正确8,这种错误得出7
15
42 194 223 321 2 54 59 8 54 4 3 6 37 97 54 32

	for(int i=0;i<n;i++){
		for(int j=0;j<i;j++){
				if(a[j]>a[i]){
				dp1[i]=max(dp1[j]+1,dp1[i]);

		}
		}
	} 

求下降子序列这两种皆可

	for(int i=n-2;i>=0;i--){
		for(int j=n-1;j>i;j--){
			if(a[j]<a[i]){
				dp1[i]=max(dp1[j]+1,dp1[i]);
			}
		}
	}
//	for(int i=n-1;i>=0;i--){
//		for(int j=i+1;j<n;j++){
//			if(a[j]<a[i]){
//				dp1[i]=max(dp1[j]+1,dp1[i]);
//			}
//		}
//	}

 #include<bits/stdc++.h>
using namespace std;

int main(){
	int n;
	cin>>n;
	int a[n];
	int dp[n];//dp[i]代表以a[i]结尾的数段(从右开始)下降序列的长度
	//相当于从左开始求上升序列(比较符合我习惯 ,,好叭,难以逃开从右开始 
//	memset(dp,1,sizeof(dp));
//	dp[0]=1;
	int dp1[n];
	for(int i=0;i<n;i++){
		cin>>a[i];
		dp[i]=1;
		dp1[i]=1;
	}

	for(int i=1;i<n;i++){
		for(int j=0;j<i;j++){
				if(a[j]<a[i]){
				dp[i]=max(dp[j]+1,dp[i]);
				//前边i个数都有对应的上升序列,找出最大的上升数+1 
		}
		}
	} 
	for(int i=n-2;i>=0;i--){
		for(int j=n-1;j>i;j--){
			if(a[j]<a[i]){
				dp1[i]=max(dp1[j]+1,dp1[i]);
			}
		}
	}
//	for(int i=n-1;i>=0;i--){
//		for(int j=i+1;j<n;j++){
//			if(a[j]<a[i]){
//				dp1[i]=max(dp1[j]+1,dp1[i]);
//			}
//		}
//	}
	int res=0;
//	int res=dp[0]+dp1[0]-1;
	//上升子序列的终点是i,下降子序列的起点是i,i这个点算了两次 
	for(int i=0;i<n;i++){
		res=max(res,dp[i]+dp1[i]-1); 
	}
	cout<<res<<endl;
//	cout<<*max_element(dp,dp+n)<<endl; 
    return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值