ABC346D 题解
题意
给出一个只包含
思路
考虑动态规划(或者说是递推)。
首先能想到的是设
然而我们发现难以从
- 转移时当前位是否要改变?这还与上一位的值有关。
- 相同的那组字符在哪?是这一位与上一位还是在这一位之前?
为了解决这两个问题,我们就要增加状态的维度,于是有了新的状态:设
接下来考虑转移:
最后是边界:显然有
答案即为
代码
#include<iostream>
#define int long long
using namespace std;
const int N=2e5+10;
int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-') w=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar();}
return s*w;
}
char s[N];
int n,a[N],c[N],f[N][2][2];//状态如上述
signed main()
{
n=read();
cin>>s;
for(int i=1;i<=n;i++) a[i]=s[i-1]-'0',c[i]=read();
f[1][0][a[1]]=0,f[1][0][!a[1]]=c[1];
f[1][1][a[1]]=f[1][1][!a[1]]=1e18;//初值
for(int i=2;i<=n;i++)
{
f[i][0][a[i]]=f[i-1][0][!a[i]];
f[i][1][a[i]]=min(f[i-1][1][!a[i]],f[i-1][0][a[i]]);//不修改
f[i][0][!a[i]]=f[i-1][0][a[i]]+c[i];
f[i][1][!a[i]]=min(f[i-1][1][a[i]],f[i-1][0][!a[i]])+c[i];//修改
}
cout<<min(f[n][1][0],f[n][1][1]);
return 0;
}