题目链接:
[HNOI2010]合唱队 - 洛谷https://www.luogu.com.cn/problem/P3205
思路:
这题我是看了题解才做出来的,贴一下这位大佬的博客题解 P3205 【[HNOI2010]合唱队】 - zhaohaikun's blog - 洛谷博客
用到了区间dp,每个人有插入到左边和右边两种可能,插入哪边与当前的人和他前面的人的谁比较高有关系。具体思路见代码。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3+5;
const int mod = 19650827;
int n;
int h[maxn];
int f[maxn][maxn][2];
/* f[i][j][0]表示的是排在第i位的人从左边插入的方案数
f[i][j][1]表示的是排在第j位的人从右边插入的方案数 */
int main(){
cin >> n;
for(int i=1; i<=n; i++){
//dp初始化,当只有一个人的时候,默认是从右边插入的
cin >> h[i];
f[i][i][1] = 1;
}
for(int len=2; len<=n; len++){
for(int i=1,j=i+len-1; j<=n; i++, j++){
//假如当前的人是插入到第i位,是从左边插入的,那说明他比在他前面一次插入的人矮
//而在他前面一次插入的人,要么插到了最左边(第i+1位),要么插到了最右边(第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];
//假如当前的人是插入到第j位,是从右边插入的,那么说明他比在他前面一次插入的人高
//而在他前面一次插入的人,要么插到最左边(第i位),要么插到最右边(第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;
}
}
cout << (f[1][n][0] + f[1][n][1]) % mod << '\n';
}