洛谷 P3205
题目链接
题目大意
给定一串序列,问有多少种初始序列经过以下操作可以得到此序列:
① 、第一个数直接插入空的当前序列中
② 、对从第二个数开始的每个数,如果它比上一个插入序列的数大,那么将它插入当前序列的最右边
如果它比上一个插入序列的数小,那么将它插入当前序列的最左边
解题思路
定义 \(dp1[i][j]\) 的含义为构成理想区间\([i , j]\) ,最后一个被放入的是 \(i\) 的方案数
定义 \(dp2[i][j]\) 的含义为构成理想区间\([i , j]\) ,最后一个被放入的是 \(j\) 的方案数
 一、
对于 \(dp1\)
区间 \([i , j]\) 的上一个区间为 \([i + 1 , j]\)
而构成区间 \([i + 1][j]\) 的序列的末尾可能是 \(a[i + 1]\) ,也可能是 \(a[j]\)
所以:
①.当 \(a[i] < a[i + 1]\) 时 , \(dp1[i][j] += dp1[i + 1][j]\)
②.当 \(a[i] < a[j]\) 时 , \(dp1[i][j] += dp2[i + 1][j]\)
 二、
对于 \(dp2\)
区间 \([i , j]\) 的上一个区间为 \([i , j - 1]\)
而构成区间 \([i][j - 1]\) 的序列的末尾可能是 \(a[i]\) ,也可能是 \(a[j - 1]\)
①.当 \(a[j] > a[i]\) 时 , \(dp2[i][j] += dp1[i][j - 1]\)
②.当 \(a[j] > a[j - 1]\) 时 , \(dp2[i][j] += dp2[i][j - 1]\)
最后 $ans = dp1[1][n] + dp2[1][n] $
注意:当 \(i = j\) 即区间长度为 \(1\) 时 , 只需让 \(dp1 = 1\) or \(dp2 = 1\) 即可
即构造区间长度为 \(1\) 的方案数只有 \(1\)
若让 \(dp1\) 和 \(dp2\) 都等于 \(1\) 则相当于构造区间长度为 \(1\) 的方案数为 \(1 + 1 = 2 (×)\)
AC_Code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10 , mod = 19650827;
int n , a[N];
int dp1[N][N] , dp2[N][N];
signed main()
{
	cin >> n;
	for(int i = 1 ; i <= n ; i ++) cin >> a[i] , dp1[i][i] = 1;
	for(int len = 1 ; len <= n ; len ++)
	{
		for(int i = 1 ; i + len <= n ; i ++)
		{
			int j = i + len; 
			{
				if(a[i] < a[i + 1]) dp1[i][j] += dp1[i + 1][j];
				if(a[i] < a[j])     dp1[i][j] += dp2[i + 1][j]; 
				if(a[j] > a[i])		dp2[i][j] += dp1[i][j - 1];
				if(a[j] > a[j - 1]) dp2[i][j] += dp2[i][j - 1];
				dp1[i][j] %= mod , dp2[i][j] %= mod;
			}
		}
	}
	cout << (dp1[1][n] + dp2[1][n]) % mod << '\n'; 
	return 0;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号