洛谷 P3205 HNOI2010 合唱队

url: https://www.luogu.com.cn/problem/P3205

tag:
动态规划,区间DP,2010

思路:
利用区间DP来做。设 f[i][j][0] 表示区间iji从左边进入区间的情况, f[i][j][1] 表示区间ijj从右边进入区间的情况。当i从左边进去时,上一个区间应该是 i + 1j ,所以只有当 h[i] < h[i + 1] 以及 h[i] < h[j] 时才能更新。同理当 h[j] > h[i] 以及 h[j] > h[j - 1] 时,j从右边进入区间,区间从 ij - 1 更新到 ij 。初始化为了避免当一个数字时有两种情况,所以可以是都假装是从左边进入区间,(或者是右边也行只要保证只保留一种情况就行)。最后答案将 f[1][n][0]f[1][n][1] 两种情况相加后取模输出即可。

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1010, mod = 19650827;
typedef long long LL;
int n;
int h[N];
LL f[N][N][2];
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> h[i];
    for (int i = 1; i <= n; i ++) f[i][i][0] = 1;
    for (int len = 1; len <= n; len ++)
    {
        for (int i = 1, j = i + len; j <= n; i ++, j ++)
        {
            if (h[i] < h[i + 1]) f[i][j][0] += f[i + 1][j][0];
            if (h[i] < h[j]) f[i][j][0] += f[i + 1][j][1];
            if (h[j] > h[i]) f[i][j][1] += f[i][j - 1][0];
            if (h[j] > h[j - 1]) f[i][j][1] += f[i][j - 1][1];
            f[i][j][0] %= mod;
            f[i][j][1] %= mod;
        }
    }
    LL res = (f[1][n][0] + f[1][n][1]) % mod;
    cout << res << endl;
    return 0;
}
添加新评论