P3205 [HNOI2010]コーラス[間隔DP]

タイトル説明

AAAのコーラスの担当者として、今後のパーティーでより良い性能の結果を持っているために、人々の小さな合唱はその高さに基づいて形成を放電する必要があります。コーラスは、N個体の合計を仮定し、i番目の個々の高さは、こんにちはメートル(1000年<=こんにちは<= 2000)で、任意の2つの人々の高さが異なっていることが知られています。Aは最終的に問題を簡単にするために、行の移動局の形成を排出していると仮定すると、小さなAは、キューイングは以下の考案:彼は次のように左から右に、人々は、初期形成にどのような順序で立つ、と押してみましょうの放電の最後のラフト形成に挿入された順番に各人物の原則:

- 現在の形成に直接空にする最初の人。

- 彼は前の人(Hより大きい)よりも背が高い場合には、誰もが二人目から開始するために、彼は一番右の現在の形成を挿入します。彼は以前の低い(小さいH)よりも男性であれば、彼は一番左の現在の形成を挿入します。

N人が完全に挿入した後に得られた場合には、この形成の形成は最終的に排出します。

例えば、そこパーソナルステーションに6つの初期形成しており、高さ1750 1850,1900,1700,1650,1800ました、

小さな形成は、次の手順の最後の放電を取得します:

1850

  • 1850年、1900年1900> 1850理由
  • 1700、1850、1900 1700 <1900理由
  • 1650.1700、1850年、1900年1650 <1700理由
  • 1650、1700、1850、1900、1800 1800> 1650理由
  • 1750、1650、1700,1850、1900年、1800年1750 <1800理由

このように、形成は1750,1650,1700,1850、1900,1800を最終的に排出されます。

小さなハートが理想の形成を持って、彼はあなたが良い初期形成の形成を得ることができますどのように多くを知りたいと思いました

説明/ヒント

30%のデータ:N <= 100

100%のデータ:N <= 1000

解決

実際には、この質問は、再帰的/レコード検索です

観察されたタイトルは、簡単にあなたが形成に参加する人を取るたびにまとめ、彼は唯一の間隔DPの性質を満たすために、左端または右端にキューに追加することができます。

セット\(DP [0/1] [I ] [J] \)は間隔を示している(私はシムj個の\を\)\をプログラムの数が最終的に右/左のほとんどの人々を置きます。

添加の原理によれば、状態遷移方程式書くことは容易である:
\ [DP [I]、[J]を[0] DPは= [I + 1] [J] [0]・[H_I <+ H_ {I} 1] + DP [。 I + 1] [j] [ 1]・[H_I <h_j] \\ DP [I] [J] [1] = DP [I]、[J - 1] [0]・[h_j> H_I] + DP [ I] [J - 1] [
1]・[h_j> H_ {J-1}] \] 私は一次元を初期化し、なぜこの問題は、比較的不思議な事(I WA数回)、初期化されているが、ゴーストが知っていると思います(\ (0/1 \)その次元)、そしてあなたの寸法に関係なく、答えは同じである初期化します。

参照コード

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define mod 19650827
#define N 1010
using namespace std;
int dp[2][N][N],n,a[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]),dp[0][i][i]=1;
    for(int len=2;len<=n;++len)
     for(int l=1;l<=n-len+1;++l){
        int r=l+len-1;
        // 0 left 1 right
        int t1=0,t2=0,t3=0,t4=0;
        if(a[l]<a[l+1]) t1=1;
        if(a[l]<a[r]) t2=1;
        if(a[r]>a[r-1]) t3=1;
        if(a[r]>a[l]) t4=1;
        dp[0][l][r]=(dp[0][l+1][r]*t1%mod+dp[1][l+1][r]*t2%mod)%mod;
        dp[1][l][r]=(dp[1][l][r-1]*t3%mod+dp[0][l][r-1]*t4%mod)%mod;
     }
    printf("%d\n",((dp[0][1][n]%mod+dp[1][1][n])%mod)%mod);
    return 0;
}

おすすめ

転載: www.cnblogs.com/DarkValkyrie/p/11295311.html