• 【BZOJ】1996: [Hnoi2010]chorus 合唱队【区间dp】


    1996: [Hnoi2010]chorus 合唱队

    Time Limit: 4 Sec  Memory Limit: 64 MB
    Submit: 2088  Solved: 1371
    [Submit][Status][Discuss]

    Description

    Input

    Output

    Sample Input

    4
    1701 1702 1703 1704

    Sample Output

    8

    HINT

     

    Source

     
    [Submit][Status][Discuss]


    HOME Back

    最讨厌统计方案数什么的了!

    但是这道题确实比较水QAQ 我们发现放数的过程实际上是区间不断向两边延伸的过程,每次更新区间当前的数只有可能是头和尾。于是想到区间DP。

    状态$f[i][j][0/1]$表示$i$到$j$区间,当前放的数在头(0)还是尾(1),如果是头就是$i$,要和$i+1$和$j$比较一下更新$dp[i][j][0]$,如果是尾就是$j$,要和$i$和$j-1$比较一下更新$dp[i][j][1]$,转移还是比较显然。

    【注意】初始化时只能把$dp[i][i][0]$或$dp[i][i][1]$其中一个赋值,如果两个都赋会导致后来的状态多出来。(长度为2时既可以更新头也可以更新尾

    #include<cstdio>
    #include<iostream>
    #define LL long long
    #define MOD 19650827
    using namespace std;
    
    int n, a[1005];
    int f[1005][1005][2];
    
    int main ( ) {
        scanf ( "%d", &n );
        for ( int i = 1; i <= n; i ++ )    scanf ( "%d", &a[i] ), f[i][i][0] = 1;
        for ( int len = 2; len <= n; len ++ )
            for ( int i = 1; i <= n - len + 1; i ++ ) {
                int j = i + len - 1;
                if ( a[j] > a[j-1] ) f[i][j][1] = ( f[i][j][1] + f[i][j-1][1] ) % MOD;
                if ( a[j] > a[i] ) f[i][j][1] = ( f[i][j][1] + f[i][j-1][0] ) % MOD;
                if ( a[i] < a[j] ) f[i][j][0] = ( f[i][j][0] + f[i+1][j][1] ) % MOD;
                if ( a[i] < a[i+1] ) f[i][j][0] = ( f[i][j][0] + f[i+1][j][0] ) % MOD;
            }
        printf ( "%d", ( f[1][n][0] + f[1][n][1] ) % MOD );
        return 0;
    }
  • 相关阅读:
    [导入]C#播放rm文件[转贴]
    新工具软件发布!名称:剪切板记录器
    黑發4/14
    sql20002 4/19
    頁面按百分比設定失調3/27
    廣告控件:AdRotator 3/23
    19992020小農曆JS 3/31
    ASP.NET1.1編譯錯誤代碼:1073741502 4/10
    SiteMapPath控件 3/24
    MYSQL時間問題4/16
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9571415.html
Copyright © 2020-2023  润新知