*PAT_甲級_1045 Favorite Color Stripe (30分) (C++)【LIS/動態規劃/晴神筆記】

目錄

1,題目描述

題目大意

輸入

輸出

說明

2,思路

核心思想

LIS問題

1,問題的定義及複雜之處 

2, 動態規劃求解問題

3,舉例

4,示例代碼

3,代碼


1,題目描述

Sample Input:

6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

 

Sample Output:

7

題目大意

(一開始確實不好理解)

有一個人叫Eva,喜歡特定的顏色按照特定的順序排列,比如{2,3,1,5,6},表示顏色2在第一位,顏色3要在2後面,顏色1要在3後面……以此類推(不必所有喜歡的顏色全部出現,剛開始一直在糾結這裏)。

這裏有一個色帶,它的顏色順序是這樣的{2 2 4 1 5 5 6 3 1 1 5 6},現在需要計算(Eva would like to have the remaining favorite stripe with the maximum length.),按照Eva喜歡的顏色順序,最長可以拼成多長的色帶(原色帶的順序保持不變)。本例中最優解有以下幾種:{2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, and {2 2 3 1 1 5 6}.

輸入

  1. 第一行: 樣例中涉及到的顏色數目N;
  2. 第二行:Eva喜歡的顏色數目M,M種顏色的編號及順序;
  3. 第三行:綵帶長度L,依次對應的顏色種類及順序;

輸出

  1. 滿足Eva喜好的顏色及順序的最大長度; 

說明

  • Eva可以辨別的顏色數目不超過200;
  • 顏色編號1-N; 

 

2,思路

這一題參考了柳神的思路,瞭解到這其實是一個LIS(Longest Increasing Sequence,最長不下降子序列)的一個變化(Eva喜歡的顏色中,排最前的賦值最小,越往後越大。並將新設定的值替換掉原先色帶的顏色編號)。於是乎,轉戰晴神筆記,瞭解一下LIS問題。

核心思想

  1. 重新聲明一個數組num,將Eva喜歡的顏色編號,按照先後順序重新賦值,比如{2 3 1 5 6},num[2]=1,num[3]=2,num[1]=3……
  2. 在接受原色帶時,剔除Eva不喜歡的顏色,並將喜歡的顏色重新編號:
  3. 此時問題便轉換爲LIS問題,並可用動態規劃求解。時間複雜度O(n^2);

 

LIS問題

以下圖片內容均來自《算法筆記》——胡凡(又稱“晴神筆記”)

1,問題的定義及複雜之處 

 

2, 動態規劃求解問題

 

3,舉例

 

4,示例代碼

 

3,代碼

#include<iostream>
#include<vector>
#include<climits>
using namespace std;

int main(){
//#ifdef ONLINE_JUDGE
//#else
//    freopen("1.txt", "r", stdin);
//#endif

    int num[201], data[10000];
    int n, m, l;                            //n涉及到的顏色數 mEva喜歡的顏色數目 l原色帶的長度
    int id, index = 0;
    cin>>n>>m;
    for(int i = 1; i <= m; i++){
        scanf("%d", &id);
        num[id] = i;                        //爲顏色出現的先後順序編號
    }

    cin>>l;
    for(int i = 0; i < l; i++){
        scanf("%d", &id);
        if(num[id] > 0){                    //只保留Eva喜歡的顏色
            data[index++] = num[id];
        }
    }

    int dp[10000], maxLen = 0;
    for(int i = 0; i < index; i++){         //原色帶處理完之後 長度爲index
        dp[i] = 1;
        for(int j = i - 1; j >= 0; j--){
            if(data[i] >= data[j])
                dp[i] = max(dp[i], dp[j]+1);//動態方程
        }
        maxLen = max(maxLen, dp[i]);        //記錄最大值
    }
    cout<<maxLen;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章