2021-01-12の動的計画法の最長xx部分列問題

1.2番目の質問

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;
		}
		
	}

}

2.ミサイルの迎撃

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;
		
	}

}

3.コーラスフォーメーション

1.トピック:

ここに画像の説明を挿入

2.問題解決:

i番目の位置に到達すると、左側の増加シーケンスと右側の減少シーケンスの合計が最大になります。i番目の位置はシーク時に2回計算されるため、-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