actoder abc 346 D - Gomamayo Sequence(线性dp)
思路
这道题贪心来想想不出,那么就是动态规划了
我们可以这么想:枚举一遍i,我们只要s[i]和s[i+1]相同(两种情况,都为1或都为0),则就要使s[1…i]和s[i+1…n]这两个字符串都符合没有相邻字符相同,那么我们就要计算出使这两个字符串符合情况的花费
转移方程
对于s[1…i],我们以dp[k][i](k=0或k=1)代表满足没有相邻字符相同且第i个字符为k的花费,对于s[i…n],我们以rdp[k][i](k=0或k=1)代表满足没有相邻字符相同且第i个字符为k的花费,见下面代码
代码
#include<iostream>
#include<algorithm>
#include<vector>
#define endl '\n'
using namespace std;
using ll = long long;
const int N = 2e5 + 10;
ll dp[2][N], rdp[2][N];
int n;
string s;
int a[N];
const ll INF = 1ll << 60;
void solve() {
cin >> n;
cin >> s;
s = '0' + s;
for (int i = 1; i <= n; i++) cin >> a[i];
for(int i=1;i<s.size();i++)
if (s[i] == '0') {
dp[0][i] = dp[1][i - 1];
dp[1][i] = dp[0][i - 1] + a[i];
}
else {
dp[0][i] = dp[1][i - 1] + a[i];
dp[1][i] = dp[0][i - 1];
}
for (int i = s.size()-1; i >= 1; i--)
if (s[i] == '0') {
rdp[0][i] = rdp[1][i + 1];
rdp[1][i] = rdp[0][i + 1] + a[i];
}
else {
rdp[0][i] = rdp[1][i + 1] + a[i];
rdp[1][i] = rdp[0][i + 1];
}
ll ans = INF;
for (int i = 1; i + 1 < s.size(); i++) {
ans = min(ans, dp[1][i] + rdp[1][i + 1]);
ans = min(ans, dp[0][i] + rdp[0][i + 1]);
}
cout << ans << endl;
}
int main() {
cin.tie(nullptr)->ios::sync_with_stdio(false);
int t = 1;
while (t--) {
solve();
}
return 0;
}