A. Balls of Buma
具体题目地址可以直接搜索题目标题
题目大意
"BBWWBB"代表不同颜色的球,要求往这个不同颜色的球构成的球段的某位置放入一个某种颜色的球,如果放入球后,如果某些相同颜色的球段由于上一个动作而变长,并且其长度至少变为3,则此段的所有球都将被消除。
- 例如"BBWWBB",放入"BBWWWBB",由于**上一个动作(放入W球)而W颜色的球段变长,且长度>=3,则W颜色的球被消除,球段变成"BBBB",由于上一个动作(消除颜色W的球)**而B颜色球段变长,且长度>=3,则B球被消除
题目求:一共有可以放入一个球然后消除所有球的位置
解题思路
显然根据题目大意,对于每一个满足要求的位置,放入的颜色必然与该位置前后的球段颜色的一种相同,比如"BBWWBB"可以在第三个位置放入W。
针对该满足要求的位置,在放入W球后,W颜色球段的长度必然发生增长且长度>=3,当W球段被消除后,因W球段被消除而引起的球段合并,必然也发生了长度的增长且长度>= 3,然后被消除……迭代直到整个球段被彻底消除。
显然,该位置只可能在球段中间,且从中间往两边游走时,匹配的相同颜色的球段长度之和必然>=3,如"CCBBWW BBCCC"。从而解题思路就是:从两边往内部游走,判断颜色是否相同,如果不相同,则必然无法满足条件;如果颜色相同且序列长度>=3,则该球段目前位置可能被消除,继续下一球段的判定。当颜色相同但序列长度<3时,无法满足条件(因合并动作使长度增加且满足>=3);当且仅当i > j 时,游走结束,此时re = 2 倍的中间序列长度,所以最后结果就是 re / 2 + 1。
"BBWWBB"中间序列是“WW”,初始态:
i=2 j=3 re = 0
BBWWBB
判断完毕:
j=1 i=4 re = 4
BBWWBB
所以,满足要求的位置共有: 4 / 2 + 1 = 3
- +1是指"WW"存在XWW,WXW,WWX共有“长度+1”个可插入位置
#include<bits/stdc++.h>
using namespace std;
int main(){
string a;
cin >> a;
int re = 0;
int i = 0;
int j = a.length() - 1;
int f = 1;
while(i <= j){
if(a[i] == a[j]){
char x = a[i];
while(a[i] == x){
i++;
re++;
}
while(a[j] == x){
j--;
re++;
}
//cout << i << " " << j << endl;
if(re < 3){
f = 0;
break;
}
if(i <= j){
re = 0;
}
}else{
f = 0;
break;
}
}
if(f == 0)
cout << "0" << endl;
else
cout << (re / 2) + 1 << endl;
return 0;
}
B. Blocks
具体题目地址可以直接搜索题目标题
题目大意
类似于翻硬币,针对序列“BWWWWWWB”,每次可以将位置i与位置i+1的硬币反转,即W变成B,B变成W,针对长度为n的序列,最多不可超过3n次,问能不能把所有硬币弄成相同的颜色
解题思路
首先,找规律。显然,当且仅当序列中的W、B的个数至少有一项为偶数时,存在解,否则无解。
为了方便处理,直接选择偶数次的元素处理。这里我们选择B,保证B必然是偶数。
- 为了保证B的次数必然是偶数:可以发现,在存在解的情况下,存在以下情况:W偶 B奇数、W偶 B偶、W奇 B偶数,当且仅当W是奇数的时候,B必然是偶数,所以,当W是奇数的时候,我们将所有的W和B互相转换,保证处理的“B”必然是偶数。
然后经过偶数次翻转,即翻转所有的B,保证最后的序列必然一致
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
int main(){
cin>>n>>s;
int ans1=0,ans2=0;
for(int i=0;i<s.size();i++)
if(s[i]=='B')
ans1++;
else
ans2++; // W
if( (ans1&1) && (ans2&1) ){
cout<<-1;
return 0;
}
if(!(ans2&1)) // if W 是偶数次的话
for(int i=0;i<s.size();i++)
if(s[i]=='W')
s[i]='B';
else
s[i]='W';
queue<int> q;
for(int i=0;i<s.size()-1;i++)
if(s[i] =='B' ){
q.push(i+1);
if(s[i+1]=='W')
s[i+1]='B';
else
s[i+1]='W';
}
cout<<q.size()<<endl;
while(!q.empty())
cout<<q.front()<<' ',q.pop();
return 0;
}
本文探讨了两种有趣的算法问题:“球段消除”要求通过放置特定颜色的球来消除所有球;“硬币翻转”则需通过翻转操作使所有硬币颜色一致。文章提供了详细的解题思路及C++实现。
12万+

被折叠的 条评论
为什么被折叠?



