洛谷P3205 合唱队

你说的曾经没有我的故事 提交于 2019-12-02 07:56:37

题目

区间dp。但是跟平常的区间dp不同的是,这个题仅仅只是运用了区间dp的通过小区间的信息更新大区间的信息,而没有运用枚举断点的区间dp一般思路。

这个题我们首先发现每个人在插入的时候一定插入到队伍的最前方或最后方,所以当要插入该数的时候,要比较的数是队伍的最前方或最后方,然后用加法原理。与其说是dp,不如说是递推。

#include <bits/stdc++.h>
#define N 1000110
#define int long long
const int mod = 19650827;
using namespace std;
int n, a[N];
int dp[1001][1001][2];// 0表示从左边 
signed main()
{
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &a[i]), dp[i][i][0] = 1;
    for (int l = 2; l <= n; l++)
        for (int i = 1; i + l - 1 <= n; i++)
        {
            int j = i + l - 1;//不需要枚举断点,因为不需要从断点转移过来, 因为当前状态的前一个插入的数必定是i+1或者j-1,然后判断 
            if (a[j] > a[j - 1])
                dp[i][j][1] += dp[i][j - 1][1];
            if (a[i] < a[j])
                dp[i][j][1] += dp[i][j - 1][0], dp[i][j][0] += dp[i + 1][j][1];
            if (a[i] < a[i + 1])
                dp[i][j][0] += dp[i + 1][j][0];
            dp[i][j][0] %= mod;
            dp[i][j][1] %= mod; 
        }
    printf("%lld", (dp[1][n][0] + dp[1][n][1]) % mod);
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!