终于我也开始做dp题了。
链接
做法1:
,
指数组
的下标,
指数组
的下标,均从1开始。
状态转移方程为:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 2e3+7;
int a[maxn];
int dp[5][maxn];
int s[] = {0,1,2,1,2};
int main(){
ios::sync_with_stdio(0);
int n;cin >> n;
for(int i = 1;i<=n;i++){
cin >> a[i];
}
for(int i = 1;i<=n;i++){
for(int type = 1;type<=4;type++){
dp[type][i] = max(dp[type-1][i],dp[type][i-1]+(a[i] == s[type]));
}
}
cout << dp[4][n] << endl;
}
做法2:
状态转移方程:
为前缀1的数量。 为后缀2的数量。
可以用方程的特性,去掉 的两个维度。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 2e3+7;
int a[maxn];
int dp[3];
int sum1[maxn],sum2[maxn];
int main(){
ios::sync_with_stdio(0);
int n;cin >> n;
for(int i = 1;i<=n;i++){
cin >> a[i];
}
for(int i = 1;i<=n;i++){
sum1[i] += sum1[i-1] + (a[i] == 1);
}
for(int i = n;i>=1;i--){
sum2[i] += sum2[i+1] + (a[i] == 2);
}
int ans = -1e9;
for(int i = 1;i<=n;i++){
memset(dp,0,sizeof(dp));
for(int j = i;j<=n;j++){
dp[1] = max(dp[1],dp[2]) + (a[j] == 1);
dp[2] = dp[2] + (a[j] == 2);
ans = max(ans,sum1[i-1]+sum2[j+1]+dp[1]);
ans = max(ans,sum1[i-1]+sum2[j+1]+dp[2]);
}
}
cout << ans << endl;
}