D2. Zero-One (Hard Version)
题意
给定
和两个01串,字符串的长度为 ,现在你可以选择一个 和 ( ),将 变成 ,将 变成 , ,则代价是 ,否则代价是 ,操作次数不限,求使两个串相同的最小代价,若无解输出-1
题解
设两个01串有
如果
-
特判一下
且这两个位置是相邻的情况,此时的答案为否则,我们总可以选
组不相邻的位置(因为选相邻总是不优的),此时答案为 -
处理出所有两个01串不同的位置,原问题等价于把这些位置分成
设这两个位置是
和 ,相邻的话显然直接操作,不相邻的话,直接操作或者移动某个位置,直到相邻后再操作 因此,最小代价为
我们在pos数组上考虑区间dp,考虑区间
首先,同组的
设
预处理区间长度为2的情况,只dp区间长度为偶数的区间,答案即为
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5007;
ll n,x,y,a[N],b[N],f[N][N],pos[N];
void read(ll &x){
char c=getchar();
x=0;
while(!isdigit(c)){
c=getchar();
}
while(isdigit(c)){
x=x*10+c-'0';
c=getchar();
}
}
ll read(){
char c=getchar();
while(c!='0'&&c!='1'){
c=getchar();
}
return c-'0';
}
ll calc(ll l,ll r){
return min((r-l)*x,y);
}
void work(){
ll i,j,cnt=0;
read(n),read(x),read(y);
for(i=1;i<=n;++i){
a[i]=read();
}
for(i=1;i<=n;++i){
b[i]=read();
}
for(i=1;i<=n;++i){
if(a[i]!=b[i]){
pos[++cnt]=i;
}
}
if(cnt%2){
puts("-1");
return;
}
if(x>=y){
if(cnt==2&&pos[2]-pos[1]==1){
printf("%lld\n",min(2*y,x));
}
else{
printf("%lld\n",cnt/2*y);
}
}
else{
for(i=1;i<cnt;++i){
f[i][i+1]=calc(pos[i],pos[i+1]);
}
for(i=4;i<=cnt;i+=2){
for(j=1;j+i-1<=cnt;++j){
ll l=j,r=j+i-1;
f[l][r]=min(min(f[l+2][r]+calc(pos[l],pos[l+1]),f[l][r-2]+calc(pos[r-1],pos[r])),
f[l+1][r-1]+calc(pos[l],pos[r]));
}
}
printf("%lld\n",f[1][cnt]);
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
work();
}
return 0;
}
分类:
ACM题解及知识点总结
标签:
codeforces
, 区间dp
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具