Red Huang

Red Huang

最長増加部分列: 動的計画法

LIS の長さを計算する

  1. int s [5];       // sequence を保存するための配列

  2. int array [5];   // x 番目の値は sequence: s [0]~s [x] の LIS の長さ

  3. int LIS()

  4. {

  5.     // 初期化、各数字は長さ 1 の部分列そのものである

  6.     for (int i=0; i<5; i++) array[i] = 1;

  7.     // LIS

  8.     for (int i=0; i<5; i++)

  9.         for (int j=i+1; j<5; j++)   // s [i] の後に続く数字を探す

  10.             if (s [j] > s [i])        // 接続可能なら、長さを増やす

  11.                 array[j] = max(array[j], array[i] + 1);

  12.     // array 中の最大値が LIS の長さである

  13.     int ans = 0;

  14.     for (int i=0; i<5; i++)

  15.         ans = max(ans, array[i]);

  16.     return ans;

  17. }

LIS を見つける

  1. int s[5];

  2. int array[5];

  3. int prev [5];    // prev [x] は s [x] がどの位置の数字の後に接続されているかを記録する

  4.                 // 前に数字がなければ - 1 を記録する

  5. int LIS()

  6. {

  7.     for (int i=0; i<5; i++) array[i] = 1;

  8.     // -1 はこの数字が他の数字の後に接続されていないことを示す

  9.     for (int i=0; i<5; i++) prev[i] = -1;

  10.     for (int i=0; i<5; i++)

  11.         for (int j=i+1; j<5; j++)

  12.             if (s[j] > s[i])

  13.                 if (array[i] + 1 > array[j])

  14.                 {

  15.                     array[j] = array[i] + 1;

  16.                     prev [j] = i;   // s [j] は s [i] の後に接続される

  17.                 }

  18.     int ans = 0, pos = 0;

  19.     for (int i=0; i<5; i++)

  20.         if (ans > array[i])

  21.         {

  22.             ans = array[i];

  23.             pos = i;

  24.         }

  25.     print_LIS (pos); // 1 つの LIS を出力する

  26.     return ans;

  27. }

  28. // 再帰版

  29. void print_LIS(int x)

  30. {

  31.     if (prev[x] != -1) print_LIS(prev[x]);

  32.     cout << seq[x] << " ";

  33. }

  34. // ループ版だが、順序は逆である。

  35. void print_LIS(int x)

  36. {

  37.     for (; prev[x] != -1; x = prev[x])

  38.         cout << seq[x] << " ";

  39. }

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。