- https://codeforces.com/contest/1733/problem/D2
- 找出对应不同的位置数组dif
对于两个不同的位置$dif_{i-1}$和$dif_i$,有四种可行的操作
- $dif_{i-1} + 1 = dif_i$,用一次x操作
- $dif_{i-1} + 1 = dif_i$,用l两次y操作
- $dif_{i-1} + 1 ≠ dif_i$,用$dif_i - dif_{i-1} $次x操作(从左到右一个一个走)
- $dif_{i-1} + 1 ≠ dif_i$,用一次y操作
- 上面的操作可以通过区间dp来实现
状态表示:$f[l][r]$表示{l,r}区间内所有匹配完成的最小cost
状态转移:类似区间dp的转移方式,len小于等于2时为0,初始全为inf
- 还有一些其他的特判
比如dif的个数为奇数,那么显然无解
- 这里代码用了记忆化搜索
#include<bits/stdc++.h>
#define debug1(a) cout<<#a<<'='<< a << endl;
#define debug2(a,b) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<endl;
#define debug3(a,b,c) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<endl;
#define debug4(a,b,c,d) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<" "<<#d<<" = "<<d<<endl;
#define debug5(a,b,c,d,e) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<" "<<#d<<" = "<<d<<" "<<#e<<" = "<<e<<endl;
#define debug0(x) cout << "debug0: " << x << endl
#define fr(t, i, n)for (int i = t; i < n; i++)
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
//#pragma GCC optimize(3,"Ofast","inline")
//#pragma GCC optimize(2)
const int N = 5010;
LL dif[N],ed;
LL n,x,y;
LL f[N][N];
LL get(LL l,LL r)
{
if(l+1 == r)return min(x,2*y);
else return min(x*(r-l),y);
}
LL dfs(LL l,LL r)
{
if(l > r)return 0;
if(f[l][r] != -1)return f[l][r];
LL res = 1e18;
res = min(res,dfs(l,r-2) + get(dif[r-1],dif[r]));
res = min(res,dfs(l+1,r-1) + get(dif[l],dif[r]));
res = min(res,dfs(l+2,r) + get(dif[l],dif[l+1]));
return f[l][r] = res;
}
void solve(){
cin >> n >> x >> y;
string s1,s2;cin >> s1 >> s2;
ed = 0;
for(int i = 0;i < n;i ++)for(int j = 0;j < n;j ++)f[i][j] = -1;
for(int i = 0;i < n;i ++)if(s1[i] != s2[i])dif[ed++] = i;
if(ed % 2)
{
cout << -1 << endl;
return ;
}
if(ed == 2)
{
cout << get(dif[0],dif[1]) << endl;
return ;
}
if(ed == 0)
{
cout << 0 << endl;
return ;
}
if(y <= x){cout << ed/2LL*y << endl;return;}
cout << dfs(0,ed-1) << endl;
}
int main()
{
/*
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
*/
int T = 1;cin >> T;
while(T--){
solve();
}
return 0;
}
- 在上面的思路O($n^2$),我们可以优化一下,直接用线性dp完成,实现O($n$)
- 学习自CF1733D2 Zero-One (Hard Version) 题解 - 灵茶山艾府 - 洛谷博客 (luogu.com.cn)
#include<bits/stdc++.h>
#define debug1(a) cout<<#a<<'='<< a << endl;
#define debug2(a,b) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<endl;
#define debug3(a,b,c) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<endl;
#define debug4(a,b,c,d) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<" "<<#d<<" = "<<d<<endl;
#define debug5(a,b,c,d,e) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<" "<<#d<<" = "<<d<<" "<<#e<<" = "<<e<<endl;
#define fr(t, i, n)for (long long i = t; i < n; i++)
#define endl "\n"
#define fi first
#define se second
#define int long long
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
//#pragma GCC optimize(3,"Ofast","inline")
//#pragma GCC optimize(2)
const int N = 5010;
LL dif[N],ed;
LL n,x,y;
LL f[N];
LL get(LL l,LL r)
{
if(l+1 == r)return min(x,2*y);
else return min(x*(r-l),y);
}
void solve(){
cin >> n >> x >> y;
string s1,s2;cin >> s1 >> s2;
ed = 0;
for(int i = 0;i < n;i ++)if(s1[i] != s2[i])dif[ed++] = i;
if(ed % 2)
{
cout << -1 << endl;
return ;
}
if(ed == 2)
{
cout << get(dif[0],dif[1]) << endl;
return ;
}
if(ed == 0)
{
cout << 0 << endl;
return ;
}
if(y <= x)cout << ed/2LL*y << endl;
else
{
fill(f,f+ed,1e15);
f[0] = y;
f[1] = min(f[0] + y,(dif[1] - dif[0])*x*2);
for(int i = 2;i < ed;i ++)
{
f[i] = min(f[i-1] + y,f[i]);
f[i] = min(f[i-2] + (dif[i] - dif[i-1])*x*2,f[i]);
}
cout << f[ed-1]/2 << endl;
}
}
signed main()
{
/*
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
*/
int T = 1;cin >> T;
while(T--){
//puts(solve()?"YES":"NO");
solve();
}
return 0;
}
/*
*/