终于我也开始做dp题了。
链接
做法1:
s=[0,1,2,1,2]
s
=
[
0
,
1
,
2
,
1
,
2
]
,
i
i
指数组的下标,
type
t
y
p
e
指数组
s
s
的下标,均从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:
状态转移方程:
sum1[i] s u m 1 [ i ] 为前缀1的数量。 sum2[i] s u m 2 [ i ] 为后缀2的数量。
可以用方程的特性,去掉 dp[] d p [ ] 的两个维度。
#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;
}
本文介绍了两种不同的动态规划(DP)算法实现方式,一种是通过状态转移方程寻找特定子序列的最大长度,另一种则是通过减少状态维度来优化计算过程。文中提供了完整的C++代码示例,帮助读者更好地理解算法细节。

196

被折叠的 条评论
为什么被折叠?



