2021-01-12动态规划的最长xx子序列问题

一. 第二题

1.题面:

在这里插入图片描述

2.题解:

  以为是01背包,测试样例正确但是段错误,

“但是这个题目没办法直接用动态规划,因为这个和会非常非常大,导致状态空间过大,会内存溢出,所以最后AC的代码还是用了搜索+剪枝,直接搜索所有可能的选择”

用·剪枝的dfs,回头补

补充:关于getline函数:

      getline 的 C++ 函数。此函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中。
      getline 函数如下所示:getline(cin, inputLine);
      其中 cin 是正在读取的输入流,而 inputLine 是接收输入字符串的 string 变量的名称。

3.代码

int main()
{
    
    
    string name;
    string city;
    cout << "Please enter your name: ";
    getline(cin, name);
    cout << "Enter the city you live in: ";
    getline(cin, city);
    cout << "Hello, " << name << endl;
    cout << "You live in " << city << endl;
    return 0;
}

段错误代码:QAQ

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
long long int dp[400000],a[400000];
using namespace std;

int main(){
    
    
	string s;
	int n;
	while(getline(cin,s)){
    
    
	//	cout<<s<<endl;
		int i,j;
		memset(dp,0,sizeof(dp));
		memset(a,0,sizeof(a));
		n=s.length();
		long long int t=0;
		j=0;
		int flag=1;
		long long int sum=0;
		for(i=0;i<n;i++){
    
    
			if(s[i]>='0'&&s[i]<='9'){
    
    
				t=t*10+s[i]-'0';	
			}else if(s[i]==' '){
    
    
				a[j]=t;
				t=0;
				sum+=a[j++];
			}else{
    
    
				flag=0;
				break;
			}
		}
		if(s[i-1]>='0'&&s[i-1]<='9'){
    
    
			a[j]=t;
			sum+=a[j++];
		}
//		for(i=0;i<n;i++){
    
    
//			cout<<a[i]<<" ";
//			
//		}
//		cout<<endl;
		if(flag==0){
    
    
			cout<<"ERROR"<<endl;
			continue;
		}else{
    
    
			for(i=0;i<j;i++){
    
    
				for(int v=sum/2;v>=a[i];v--){
    
    
					dp[v]=max(dp[v],dp[v-a[i]]+a[i]);
				}
			}
			int a=dp[sum/2],b=sum-dp[sum/2];
			
			cout<<b<<" "<<a<<endl;
		}
		
	}

}

二.拦截导弹

1. 题面:

在这里插入图片描述

2. 题解:反过来求最长不降子序列

3.ac代码

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
long long int dp[400000],a[400000];
using namespace std;

int main(){
    
    
	int n,i,j;
	while(cin>>n&&n){
    
    
		for(i=0;i<n;i++){
    
    
			cin>>a[i];
		}
		
		for(i=n-1;i>=0;i--){
    
    
			dp[i]=1;
			for(j=n-1;j>i;j--){
    
    
				if(a[j]<=a[i])
				dp[i]=max(dp[i],dp[j]+1);
			}
		}
		int ans=0;
		for(i=0;i<n;i++){
    
    
			if(dp[i]>ans)
			ans=dp[i];
		}
		cout<<ans<<endl;
		
	}

}

三.合唱队形

1. 题面:

在这里插入图片描述

2.题解:

到第i位置时左边递增序列,右边递减序列的和最大,在求时第i位置被算了两次,所以要-1,n-(max-1)

3.ac代码

#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
long long int dp2[400000],dp1[400000],a[400000];
using namespace std;

int main(){
    
    
	int n,i,j;
	while(cin>>n&&n){
    
    
		for(i=0;i<n;i++){
    
    
			cin>>a[i];
		}
		
		for(i=n-1;i>=0;i--){
    
    
			dp2[i]=1;
			for(j=n-1;j>i;j--){
    
    
				if(a[j]<a[i])
				dp2[i]=max(dp2[i],dp2[j]+1);
			}
		}
		for(i=0;i<n;i++){
    
    
			dp1[i]=1;
			for(j=0;j<i;j++){
    
    
				if(a[j]<a[i])
				dp1[i]=max(dp1[i],dp1[j]+1);
			}
		}
		int ans=0;
		for(i=0;i<n;i++){
    
    
			if(dp1[i]+dp2[i]>ans)
			ans=dp1[i]+dp2[i];
		}
		cout<<n-ans+1<<endl;
		
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_46064382/article/details/112546850