区间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; }