P3205 [HNOI2010] 合唱队
P3205 [HNOI2010] 合唱队
题目翻译:
太简单了,就不翻译了
思路:
一道很不像区间\(dp\)的区间\(dp\),我们知道,不管是理想队形,还是初始队形,其大小都为\(n\),那我们令\(i,j\)表示已经加入的队形在最终队形的\(i\)到\(j\)中则令\(f[i][j][0]\)表示把点从左边加入第\(i\)人,而\(f[i][j][1]\)表示将第\(j\)人从右边加入。由此可以推出三种情况:
先令第\(i\)个人的高度为\(h[i]\)
\(1.\)若上一个人是第\(i+1\)个,则有\(h[i]<h[i+1]\)那也就是说它比上一个人矮,那就应该加到右边。
\[$dp[i][j][0]+=dp[i+1][j][0] (h[i]<h[i+1])$ \]\(2.\)若上一个人是\(j\)那它上次就是从右边加入,而\(h[i]<h[j]\),则它比上一个矮,那它就应该从左边加入,则:
\[$dp[i][j][0]+=dp[i+1][j][1] (h[i]<h[j])$ \]\(3.\)若上一个人是\(j-1\)而我的高度\(h[j]>h[j-1]\),那我比上一个高,就应该从右边加入,则:
\[$dp[i][j][1]+=dp[i][j-1][1] (h[j-1]<h[j])$ \]\(4.\)若上一个人是\(i\),且我的高度\(h[j]>h[i]\)则我还是因该从右边加入,则
\[$dp[i][j][1]+=dp[i][j-1][0] (h[j]>h[i])$ \]
为了保证\(dp\)时所有子区间已经\(dp\),则我们根据长度\(dp\)即可
完整代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2000;
const int P=19650827;
int dp[N][N][2];
int h[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>h[i];
dp[i][i][0]=1;
}
for(int len=1;len<=n;len++){
for(int i=1;i<=n-len+1;i++){
int j=i+len-1;
if(h[i]<h[i+1])dp[i][j][0]+=dp[i+1][j][0];
if(h[i]<h[j])dp[i][j][0]+=dp[i+1][j][1];
if(h[j]>h[i])dp[i][j][1]+=dp[i][j-1][0];
if(h[j]>h[j-1])dp[i][j][1]+=dp[i][j-1][1];
dp[i][j][0]%=P;
dp[i][j][1]%=P;
}
}
cout<<(dp[1][n][0]+dp[1][n][1])%P<<endl;
}
区间\(DP\)讲解
本文作者:XichenOC
本文链接:https://www.cnblogs.com/XichenOC/p/18682393
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步