BZOJ1996&&洛谷P3205 [HNOI2010]合唱队

版权声明:我这么弱的蒟蒻,虽然博文不是很好,但也请标明转发地址喵! https://blog.csdn.net/ACerAndAKer/article/details/82217111

区间dp

我们考虑两个数组f[i][j]和g[i][j]

f[i][j]表示构成理想区间i~j,最后一个插进去的是i的方案,g[i][j]表示构成理想区间i~j,最后一个插进去的是j的方案

对于f[i][j]

1.前一个插进去的是i+1,那么i能插到i+1左边的条件是a[i]<a[i+1]--->f[i+1][j]

2.前一个插进去的是j,那么i能插到i+1左边的条件是a[i]<a[j]--->g[i+1][j]

所以f[i][j]=f[i+1][j]*(a[i[<a[i+1])+g[i+1][j]*(a[i]<a[j])

对于g[i][j]

1.前一个插进去的是i,那么j能插到j-1的右边的条件是a[j]>a[i]--->f[i][j-1]

2.前一个插进去的是j-1,那么j能插到j-1的右边的条件是a[j]>a[j-1]--->g[i][j-1]

所以g[i][j]=f[i][j-1]*(a[i]<a[j])+g[i][j-1]*(a[j]>a[j-1])

然后初始的时候f[i][i]=1,然后正常区间dp就好了

代码

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm> 
using namespace std;
const int M=1050;
const int mod=19650827;
int n,f[M][M],a[M],g[M][M];
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
signed main()
{
	n=read();
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=1;i<=n;i++) f[i][i]=1;
	for (int i=1;i<n;i++)
	for (int k=1;k+i<=n;k++)
	f[k][i+k]=(f[k+1][i+k]*(a[k]<a[k+1])+g[k+1][i+k]*(a[k]<a[k+i]))%mod,
	g[k][i+k]=(f[k][i+k-1]*(a[k]<a[i+k])+g[k][i+k-1]*(a[i+k]>a[i+k-1]))%mod;
	cout<<(f[1][n]+g[1][n])%mod;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ACerAndAKer/article/details/82217111