[ABC346D] Gomamayo Sequence 讲解
题目
一眼 dp。
做法一:
从一端开始 dp,设
易得转移方程:
初始化:
直接放代码:
#include<bits/stdc++.h>
#define int long long
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define per(i,x,y) for(int i=x;i>=y;--i)
#define repe(i,x,y,z) for(int i=x;i<=y;i+=z)
#define eper(i,x,y,z) for(int i=x;i>=y;i-=z)
#define fst ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define inl inline
#define INF LLONG_MAX
using namespace std;
const int N=2e5+5;
int n,c[N],f[N][5][5];
string s;
signed main(){
fst;
memset(f,0x3f,sizeof(f));
cin>>n>>s;
s='2'+s;
rep(i,1,n) cin>>c[i];
f[2][0][0]=(s[1]=='0')*c[1]+(s[2]=='1')*c[2];
f[2][1][0]=(s[1]=='1')*c[1]+(s[2]=='0')*c[2];
f[2][0][1]=(s[1]=='1')*c[1]+(s[2]=='1')*c[2];
f[2][1][1]=(s[1]=='0')*c[1]+(s[2]=='0')*c[2];
rep(i,3,n){
f[i][0][0]=f[i-1][1][0]+(s[i]=='1')*c[i];
f[i][1][0]=f[i-1][0][0]+(s[i]=='0')*c[i];
f[i][0][1]=min(f[i-1][1][1],f[i-1][0][0])+(s[i]=='1')*c[i];
f[i][1][1]=min(f[i-1][0][1],f[i-1][1][0])+(s[i]=='0')*c[i];
}
// rep(i,1,n) cout<<f[i][0][0]<<' '<<f[i][0][1]<<' '<<f[i][1][0]<<' '<<f[i][1][1]<<endl;
cout<<min(f[n][0][1],f[n][1][1]);
return 0;
}
做法二:
考虑好字符串的本质,实际就是中间两位相同的两个交错字符串,所以我们可以从两端进行 dp,设
转移方程与做法一类似,直接放代码:
#include<bits/stdc++.h>
#define int long long
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define per(i,x,y) for(int i=x;i>=y;--i)
#define repe(i,x,y,z) for(int i=x;i<=y;i+=z)
#define eper(i,x,y,z) for(int i=x;i>=y;i-=z)
#define fst ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define inl inline
#define INF LLONG_MAX
using namespace std;
const int N=2e5+5;
int n,c[N],f[N][5],g[N][5],ans=INF;
string s;
signed main(){
fst;
cin>>n>>s;
s=' '+s;
rep(i,1,n) cin>>c[i];
rep(i,1,n){
f[i][0]=(s[i]=='1')*c[i]+f[i-1][1];
f[i][1]=(s[i]=='0')*c[i]+f[i-1][0];
}
per(i,n,1){
g[i][0]=(s[i]=='1')*c[i]+g[i+1][1];
g[i][1]=(s[i]=='0')*c[i]+g[i+1][0];
}
rep(i,1,n-1){
ans=min(ans,f[i][0]+g[i+1][0]);
ans=min(ans,f[i][1]+g[i+1][1]);
}
cout<<ans;
return 0;
}