P1091 [NOIP2004 提高组] 合唱队形
传送门已部署,我们的行动会更加便利!
这个题是最长子序列问题,推荐学习最长子序列视频:BV137411B7BN
注意,题目说已经站好队,我们从左到右进行筛选,最后站好的是一个中间高,两边低的队形
我们只需要找到一个最长子序列,和一个最短子序列,最后从这两个中一起找到一个最大的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=105;
int n,dp[maxn],arr[maxn],pd[maxn],ans=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>arr[i];
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(arr[i]>arr[j])
dp[i]=max(dp[i],dp[j]+1);
}
}
for(int i=n;i>=1;i--){
pd[i]=1;
for(int j=n;j>i;j--){
if(arr[i]>arr[j])
pd[i]=max(pd[i],pd[j]+1);
}
}
// for(int i=1;i<=n;i++)
// cout<<dp[i]<<" ";
// cout<<endl;
//
// for(int i=1;i<=n;i++)
// cout<<pd[i]<<" ";
// cout<<endl;
for(int i=1;i<=n;i++)
ans=max(ans,dp[i]+pd[i]-1);
cout<<n-ans;
}
P1077 [NOIP2012 普及组] 摆花
这个题我们只需要找到状态转移方程,打出dp表就好了,有因为满足后无效性原则,可以创建二维dp表,也可以使用一维dp表
dp[i][j]=(dp[i][j]+dp[i-1][j-k])%mod;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=105;
int n,m,mod=1000000+7;
int arr[maxn],dp[maxn][maxn];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>arr[i];
dp[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++){
for(int k=1;k<=min(arr[i],j);k++)
dp[i][j]=(dp[i][j]+dp[i-1][j-k])%mod;
}
cout<<dp[n][m]<<endl;
return 0;
}
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=105; int n,m,mod=1000000+7; int arr[maxn],dp[maxn]; int main(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>arr[i]; dp[0]=1; for(int i=1;i<=n;i++) for(int j=m;j>=0;j--){ for(int k=1;k<=min(arr[i],j);k++) dp[j]=(dp[j]+dp[j-k])%mod; } cout<<dp[m]<<endl; return 0; }