n 个砖块排成一排,从左到右编号依次为 1∼n。
每个砖块要么是黑色的,要么是白色的。
现在你可以进行以下操作若干次(可以是 0 次):
选择两个相邻的砖块,反转它们的颜色。(黑变白,白变黑)
你的目标是通过不超过 3n 次操作,将所有砖块的颜色变得一致。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含一个整数 n。
第二行包含一个长度为 n 的字符串 s。其中的每个字符都是 W
或 B
,如果第 i 个字符是 W
,则表示第 i 号砖块是白色的,如果第 i 个字符是 B
,则表示第 i 个砖块是黑色的。
输出格式
每组数据,如果无解则输出一行 −1。
否则,首先输出一行 k,表示需要的操作次数。
如果 k>0,则还需再输出一行 kk 个整数,p1,p2,…,pk。其中 pi 表示第 i 次操作,选中的砖块为 pi 和 pi+1号砖块。
如果方案不唯一,则输出任意合理方案即可。
数据范围
1≤T≤10,
2≤n≤200。
输入样例:
4
8
BWWWWWWB
4
BWBB
5
WWWWW
3
BWB
输出样例:
3
6 2 4
-1
0
2
2 1
题解
特殊情况:
- 当B和w都为奇数,则一定无法翻转出来,最终一定会得到最后一个相邻的为WB,翻转为BW循环下去无法结局
- 当B或者W的数量为0时,则0次就可以成功。
- 正常情况可解即B、W有一个为偶数,解法如下:
- 首先将w都转移到最右端
- 如果遇到当前和下一个都是w,那就变成b
- 若当前是w,下一个是b,则翻转w移动到下一个
- 若当前是b,不动
- 所有w都到最右端后,如果b是偶数,则全部翻转b,否则全部翻转w
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
string s;
cin>>s;
int b_cnt = 0, w_bnt = 0;
for(int i =0;i<n;i++){
if(s[i] == 'W') w_bnt++;
else b_cnt++;
}
if(w_bnt%2 and b_cnt%2) cout<<-1<<endl;
else if(w_bnt == 0 or b_cnt == 0) cout<<0<<endl;
else{
vector<int> ans;
// 首先将w都转移到最右端
// 如果遇到当前和下一个都是w,那就变成b
// 若当前是w,下一个是b,则翻转w移动到下一个
// 若当前是b,不动
for(int i = 0;i<n-1;i++){
if(s[i] == 'W' and s[i+1] == 'B'){
ans.push_back(i);
s[i] = 'B';
s[i+1] = 'W';
}else if(s[i] == 'W' and s[i+1] == 'W'){
ans.push_back(i);
s[i] = 'B';
s[i+1] = 'B';
}
}
if(w_bnt%2 == 0){
// w -> b
for(int i = 0;i<n-1;i++){
if(s[i] == 'W' and s[i+1] == 'W'){
ans.push_back(i);
s[i] = 'B';
s[i+1] = 'B';
}
}
}else{
// b -> w
for(int i = 0;i<n-1;i++){
if(s[i] == 'B' and s[i+1] == 'B'){
ans.push_back(i);
s[i] = 'W';
s[i+1] = 'W';
}
}
}
printf("%d\n",ans.size());
for(int i = 0;i<ans.size();i++) cout<<ans[i]+1<<" ";
printf("\n");
}
}
return 0;
}