题意:
给出一个由(n-1)个("A"),(n-1)个("B")和两个连续的空位置(用(".")表示)构成的长(2*n)的字符串(N<=100)
现在可以进行不超过1000次的操作使得任意字符A前没有字符B
每次操作如下:选择两个连续的字符,将他们放到空的两个位置上
输出最小修改次数及方案
题解:
考虑对序列进行操作后最左侧为A,最右侧为B,这样解决子问题就行了
可以发现只要序列长度大于4,总可以进行以上操作
那么对于序列长度=4时,分类讨论即可
若此时已经满足条件,完成
否则,若序列原长度为4,则无解
若原长=6
ABA..B →→ ..AABB
A..BAB →→ AABB..
AB..AB →→无解
若原长>=8,原来无解的情况也有解
AAB..ABB →→ ..BAAABB→→ AABA..BB →→ A..AABBB
code:
#include<bits/stdc++.h>
using namespace std;
int n,pos;
bool flag;
string s;
vector<string>ans;
inline void update(int x)
{
swap(s[x],s[pos]);swap(s[x+1],s[pos+1]);
ans.push_back(s);
pos=x;
}
inline void work(int l,int r)
{
if(r-l+1>4)
{
if(s[l]!='A')
{
if(pos==l+1)update(l+3);
if(pos!=l)update(l);
for(int i=l+2;i<r;++i)
if(s[i]=='A'){update(i);break;}
}
if(s[r]!='B')
{
if(pos==r-2)update(r-4);
if(pos!=r-1)update(r-1);
for(int i=r-2;i>l;--i)
if(s[i]=='B'){update(i-1);break;}
}
work(l+1,r-1);
}
else
{
for(int i=l;i<=r;++i)
{
if(s[i]=='A')return;
if(s[i]=='B')break;
}
if(n==2){flag=1;return;}
if(s[l]=='B'&&s[l+1]=='A'){update(l-1);return;}
if(s[r]=='A'&&s[r-1]=='B'){update(r);return;}
if(n==3)flag=1;
else update(l-2),update(r-1),update(l-1);
return;
}
}
int main()
{
scanf("%d",&n);
if(n==1)return puts("0"),0;
cin>>s;
for(int i=0;i<2*n;++i)
if(s[i]=='.'){pos=i;break;}
work(0,2*n-1);
if(flag)puts("-1");
else
{
printf("%d
",ans.size());
for(size_t i=0;i<ans.size();++i)
cout<<ans[i]<<endl;
}
return 0;
}