题解:CF1733D2 Zero-One (Hard Version)

思路分析

为了方便,我们可以先将二进制位不同的位置存起来。下文中的 \(cnt\) 代指不同的位置个数,\(a_i\) 代表第 \(i\) 个不同位置的下标。

我们发现,每次取反的时候 \(cnt\) 奇偶性是不变的,所以当 \(cnt\) 为奇数时,一定是无解的。

接着我们可以先求解 \(y \le x\) 的情况。

我们发现,若 \(cnt\) 大于等于 \(4\) 的话,我们一定可以将位置个数分为两份,前面的每个位置作为 \(l\),后面的位置作为 \(r\),这样就可以用最少的次数 \(\frac{cnt}{2}\) 与最小的代价 \(y\) 来达到最小的答案 \(\frac{cnt}{2} \times y\)。当 \(cnt=2\) 的时候,此时的答案是固定的,若两个位置相邻即为 \(x\),否则答案为 \(y\)

而对于 \(y > x\) 的情况,我们考虑 dp。

\(dp_i\) 为前 \(i\) 位匹配成功的最小代价,注意,当 \(i\) 为奇数时,\(dp_i\) 为空了一位的最小代价。

考虑如何进行转移。因为 \(x < y\),所以我们需要尽可能多的使用 \(x\)

  • 若当前位使用了第一种操作,因为 \(a_i\)\(a_{i-1}\) 之间的下标差一定最小,所以我们考虑从上一位进行转移。我们考虑将 \(a_{i-1}\)\(a_{i-1}+1\) 位置取反,将 \(a_{i-1}+1\)\(a_{i-1}+2\) 位置取反等等,所以一共会取反 \(a_i-a_{i-1}\) 次,代价就是 \((a_i-a_{i-1}) \times x\),所以我们可以从 \(dp_{i-2}\) 进行转移,这样不会影响到当前位与 \(i-1\) 位的操作,转移就是:

\[dp_i=dp_{i-2}+(a_i-a_{i-1}) \times x \]

  • 若当前位使用了第二种操作,则我们需要判断一下当前位的奇偶性。若当前位为奇数,因为当前一定有一位没有被选,所以和上一位操作次数相等,直接转移即可。若当前位为偶数,则一定增加了一次操作次数,所以加上 \(y\) 就行了。转移为:

\[dp_i=\begin{cases}dp_{i-1}&i \mod 2 = 1\\dp_{i-1}+y&i \mod 2 = 0\end{cases} \]

所以转移就是:

\[dp_i=\begin{cases}\min(dp_{i-1},dp_{i-2}+(a_i-a_{i-1})\times x)&i \mod 2 = 1\\\min(dp_{i-1}+y,dp_{i-2}+(a_i-a_{i-1})\times x)&i \mod 2 = 0\end{cases} \]

AcCode

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int N=5010;

int n,x,y,cnt;
int a[N],dp[N];

string s1,s2;

inline int read(){
	int t=0,f=1;
	register char c=getchar();
	while(c<'0'||c>'9') f=(c=='-')?(-1):(f),c=getchar();
	while(c>='0'&&c<='9') t=(t<<3)+(t<<1)+(c^48),c=getchar();
	return t*f;
}

void solution(){
	/*

	*/
}

void solve1(){
	if(cnt==2&&a[1]+1==a[2]){
		cout<<min(x,2*y)<<'\n';
		return;
	}
	if(x>=y){
		cout<<cnt/2*y<<"\n";
		return;
	}
}

signed main(){
	int T=read();
	while(T--){
		n=read(),x=read(),y=read();
		cin>>s1>>s2;
		cnt=0;
		for(int i=0;i<n;i++)
			if(s1[i]!=s2[i]) a[++cnt]=i;	
		if(cnt&1){
			cout<<-1<<"\n";
			continue;
		}
		if(x>=y) solve1();
		else{
			for(int i=2;i<=cnt;i++){
				if(i&1) dp[i]=min(dp[i-1],dp[i-2]+(a[i]-a[i-1])*x);
				else dp[i]=min(dp[i-1]+y,dp[i-2]+(a[i]-a[i-1])*x);
			}
			cout<<dp[cnt]<<'\n';
		}
	}
	return 0;
}

posted @ 2025-03-27 10:06  ask_silently  阅读(14)  评论(0)    收藏  举报