P3205 [HNOI2010] [합창 간격 DP]

제목 설명

AAA 코러스를 담당하는 사람으로, 곧 당에 더 나은 성능 결과를하기 위해 사람들의 작은 합창은 높이에 따라 형성을 배출해야합니다. 코러스가 N 개인의 총 가정, i 번째 개인의 높이 하이 미터 (1,000 <= 안녕하세요 <= 2000), 그리고 두 사람의 높이가 다른 것으로 알려져있다. A는 마지막으로 문제를 단순화하기 위해, 행의 개인 역 형성을 배출 가정, 작은 A는 대기가 다음과 고안 : 그 다음에 왼쪽에서 오른쪽으로 사람들이 다음 초기 형성과 임의의 순서로 서서 눌러 보자 방전의 최종 뗏목 형성 삽입 차례로 각자의 원리 :

- 첫 번째 사람은 현재 형성에 직접 비울 수 있습니다.

- 그 전면 (큰 H)에서보다 키 인 경우 모두를 위해 그리고는 가장 오른쪽의 전류 형성에 삽입되며, 상기 제 사람부터. 그는 이전의 낮은 (작은 H)보다 사람이 있다면, 그는 맨 왼쪽의 현재 형성을 삽입합니다.

N 명 전체 삽입 후 얻을 때이 형성 형성은 결국 소진.

예를 들어,이 개인 방송국 여섯 개 초기 형성하고, 높이 1750 1850,1900,1700,1650,1800 있었다

작은 형성은 다음 단계의 최종 방전을 얻을 :

1,850

  • 1850 1900 1900> 1850 때문에
  • 1700, 1850, 1900 <1900 1700 때문에
  • 1650.1700 1850 1900 때문에 1,650 <1,700
  • 1,650, 1,700, 1,850, 1,900, 1,800 1,800> 1,650 때문에
  • 1750, 1650, 1700,1850, 1900, 1800 <1800 1750 때문에

따라서, 최종적으로 형성 1750,1650,1700,1850, 1900,1800를 배출

작은 심장, 그는 당신이 좋은 초기 형성 형성을 얻을 수 있습니다 얼마나 많은 알고 이상적인 형성을 원했다

설명 / 팁

30 %의 데이터 : N <= 100

100 % 데이터 : N <= 1000

결심

사실,이 문제는 재귀 / 기록 검색입니다.

관찰 된 제목은 쉽게 형성에 참여하는 사람을 촬영할 때마다 요약, 그는 단지 간격 DP의 성격에 맞게, 맨 왼쪽 또는 맨 오른쪽에있는 큐에 추가 할 수 있습니다.

설정 \ (DP [0/1] [내가 ] [j는] \) 간격을 나타냅니다 \ (내가 시뮬레이션 J의 \를 \) 프로그램의 수는 마지막으로 좌 / 가장 왼쪽에있는 사람을 넣어.

첨가의 원리에 따르면, 상태 천이 방정식 작성하기 쉽다 :
\ [DP [I] [J]를 [0] DP는 = I + 1] [J] [0] · [H_i <+ H_ {I} 1] + DP [.. 난 + 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