zoukankan      html  css  js  c++  java
  • luogu P3205 合唱队

    银月城传送门

    又一道区间的dp。

    状态dp[i][j]表示队列中i——j可行的排列方法。

    首先定义边界:对于每一个点,dp[i][i]=1(显然)

    然后导一下状态转移方程,大区间必然由小区间转移而来,但是转移方法可以有多种。完成区间排列的最后一步,既可以由在左边插入i完成,也可以通过在右边插入j完成。

    方便判断,在状态上再加一维,即dp[i][j][0/1],最后一维为0则从左插入i,为1则从右插入j。

    每个状态只跟上一个状态有关,但上一个状态并不确定是从左还是右插入,因此需要进行分类讨论:

    当右端点的数大于上一个且上一个插入在右端时:f[ i ][ j ][ 1 ] += f[ i ][j - 1][ 1 ];

    当右端点的数大于左端点且上一个插入在左端时:f[ i ][ j ][ 1 ] += f[ i ][ j - 1 ][ 0 ];

    当左端点的数小于后一个且上一个插入在左端时:f[ i ][ j ][ 0 ] += f[ i + 1 ][ j ][ 0 ];

    当左端点的数小于右端点且上一个插入在右端时:f[ i ][ j ][ 0 ] += f[ i + 1 ][ j ][ 1 ];

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n[1005],dp[1005][1005][2];
    int main()
    {
        int a;
        cin>>a;
        for(int i=1;i<=a;i++)
        cin>>n[i];
        for(int i=1;i<=a;i++)
        dp[i][i][0]=1;
        for(int l=2;l<=a;l++)
    {
        for(int i=1;i<=a-l+1;i++)
        {
            int j=i+l-1;
            if(n[j]>n[j-1])
                dp[i][j][1]+=dp[i][j-1][1];
            if(n[j]>n[i])
                dp[i][j][1]+=dp[i][j-1][0];
            if(n[i]<n[i+1])
                dp[i][j][0]+=dp[i+1][j][0];
            if(n[i]<n[j])
                dp[i][j][0]+=dp[i+1][j][1];
            dp[i][j][0]%=19650827;
            dp[i][j][1]%=19650827; 
        }
    }
        cout<<((dp[1][a][0]+dp[1][a][1])%19650827);
        return 0;
    }
  • 相关阅读:
    详解javascript中的闭包
    Cookie/Session的机制与安全
    session详解
    linux常用目录简介
    对比cp和scp命令 将数据从一台linux服务器复制到另一台linux服务器
    webpack打包速度和性能再次优化
    pc浏览器css和js计算浏览器宽度的差异以及和滚动条的关系
    chrome浏览器Timing内各字段解析
    深入理解-CLI与PHP-FPM
    swool教程链接汇总
  • 原文地址:https://www.cnblogs.com/charlesss/p/10338558.html
Copyright © 2011-2022 走看看