您的位置:首页 > 其它

洛谷 P1091 NOIP 2004 合唱队形(动态规划)

2017-07-24 09:24 113 查看


题目适合已经有一定动态规划基础的去做,如果从未了解过动态规格请看我的另一篇博客:

love_phoebe的博客 求单调递增最长子序列

排合唱队形就是中间高两边递减,给出思路:

求每一个位置i的两个值:

一个是从0到末尾的最长递增子序列dpl[i]

dpl[0]=1;
for(i=1;i<N;i++){
int max=0,w;
for(w=0;w<i;w++){
if(a[w]<a[i]&&dpl[w]>max)max=dpl[w];
}
dpl[i]=max+1;
}


一个是从末尾到0的最长递增子序列dpr[i]

dpr[N-1]=1;
for(i=N-2;i>=0;i--){
int max=0,w;
for(w=i+1;w<N;w++){
if(a[i]>a[w]&&dpr[w]>max)max=dpr[w];
}
dpr[i]=max+1;
}


对于位置i,dpl[i]是0到i的最长递增子序列,dpr[i]是i到末尾的最长递减子序列

那么位置i需要的人数便是sum[i]=dpl[i]+dpr[i]-1(减一是因为两次都把i算在内)

最后求sum[]数组的最大值便是所需的最多人数,用总人数减去便是答案。

完整代码如下:

#include<iostream>
#include<cstring>
const int M=105;
int a[M],dpl[M],dpr[M];
using namespace std;
int main(){
int N,i,n;
int lin1,lin2;
cin>>N;
for(i=0;i<N;i++)cin>>a[i];
dpl[0]=1; for(i=1;i<N;i++){ int max=0,w; for(w=0;w<i;w++){ if(a[w]<a[i]&&dpl[w]>max)max=dpl[w]; } dpl[i]=max+1; }
dpr[N-1]=1; for(i=N-2;i>=0;i--){ int max=0,w; for(w=i+1;w<N;w++){ if(a[i]>a[w]&&dpr[w]>max)max=dpr[w]; } dpr[i]=max+1; }
int max=-1,sum;
for(i=0;i<N;i++){
sum=dpl[i]+dpr[i];
if(sum>max)max=sum;
}
max-=1;
printf("%d",N-max);
return 0;
}

//大一菜鸟,有错误欢迎评论ヾ(๑╹◡╹)ノ"ヾ(๑╹◡╹)ノ"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: