翻转

  • Code Level: ※
  • Thinking Level: ※※

Description

两个长为n的01串A和B
进行3种操作:

  1. A循环左移
  2. B循环右移
  3. 使一个Bi=1的i所对应的ai值异或1
    以最小操作使A变成B

Solution

对于此类问题,因为明确了目标状态
我们的一个套路是求出A中每一位到状态B的代价,去构造最优解
对于整个数组我们枚举一个移动数
然后去观察每一个位上若要达到最终态需要的花费
发现需要进行异或操作的位必须在左移或者右移的过程中异或
所以用stl维护一下,最终统计往右移的最大值和往左移的最大值就可以了

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<bits/stdc++.h>
using namespace std;
const int nn=2015;
int n,m,l[nn],r[nn],ans=0x3f3f3f3f;
char s1[nn],s2[nn];
vector<pair<int,int> >q;
void prepare(){
int i,now;
for(i=0;i<n;i++){
now=i;
while(s2[now]!='1') l[i]++,now=(now-1+n)%n;
now=i;
while(s2[now]!='1') r[i]++,now=(now+1)%n;
}
}
int main(){
int i,j,mov=0,chg=0,maxr,maxl,far;
scanf("%s%s",s1,s2); n=strlen(s1);
for(i=0;i<n;i++)if(s2[i]=='1'){mov=1;break;}
if(!mov){
printf("-1\n");return 0;
}
prepare();
for(mov=-n+1;mov<n;mov++){
far=abs(mov);
q.clear(); chg=0;
for(i=0;i<n;i++){
if(s1[i]==s2[(i+mov+n)%n]) continue ; chg++;
if(mov<=0&&l[i]<=far) continue ; if(mov>=0&&r[i]<=far) continue ;
q.push_back(make_pair(l[i],r[i]));
}
sort(q.begin(),q.end());
if(mov>0) maxr=mov; else maxr=0; j=q.size()-1;
for(maxl=n-1;maxl>=0&&maxl>=-mov;maxl--){
while(j>=0&&q[j].first>maxl){
maxr=max(maxr,q[j].second);
j--;
}
ans=min(ans,chg+(maxr+maxl)*2-far);
}
}
printf("%d\n",ans);
return 0;
}