1. 程式人生 > >動態規劃——最長單調遞增子序列

動態規劃——最長單調遞增子序列

題目描述

用動態規劃設計一個演算法,要求找出由n個整陣列成的序列的最長單調遞增子序列的個數(假設所有的元素都不相同)。

輸入

第一行輸入一個整數,表示有n個整數。

第二行輸入n個整數。

輸出

第三行輸出最長單調遞增子序列的個數。

樣例輸入

6
1 3 2 5 4 0

樣例輸出

3

思路:還是動態規劃的思想,定義一個數組longest[MAX],longest[a]表示在前a項中最長的子序列長度,一開始陣列元素全部初始化為1。然後外面一層迴圈從第二元素開始迴圈(因為longest[0]肯定是1),一直到最後一個元素,第二個迴圈從第一個元素開始迴圈到外迴圈的前一個元素,只要外面迴圈代表的這個元素,比裡面迴圈代表的元素大,那麼就判斷外迴圈的longest值(longest[i])是否小於內迴圈的longest+1的值(longest[j]+1) 因為外迴圈每次迴圈都能得到一個最優的longest 所以到最後在longest裡面找到的最大的值 即為整個陣列中最長遞增子序列的長度。動態轉移方程即為:

if(arr[i]>arr[j]){
  longest[i]=max(longest[i],longest[j]+1);
}

AC程式碼:

#include <iostream>
#include <string.h>
using namespace std;

const int MAX=1000;

int find(int arr[],int n);

int main(void){
	int n;
	int arr[MAX];
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>arr[i];
	}
	int max=find(arr,n);//尋找最優值 
	cout<<max<<endl;
	return 0;
}

int find(int arr[],int n){
	int longest[MAX];
	fill(longest,longest+n,1);
	for (int j=1; j<n; j++) {  
        for (int i=0; i<j; i++) {  
            if (arr[j]>arr[i] && longest[j]<longest[i]+1){ //注意longest[j]<longest[i]+1這個條件,不能省略。因為必須保證是最優值。  
                longest[j] = longest[i] + 1; //計算以arr[j]結尾的序列的最長遞增子序列長度  
            }  
        }  
    } 
	int max=0;
	for(int i=0;i<n;i++){//尋找Longest最優數組裡面的最大值 即為答案 
		if(max<longest[i]){
			max=longest[i];
		}
	}
	return max;
}