洛谷P1203 [USACO1.1] 坏掉的项链 Broken Necklace 题目解析
题目描述
你有一条由 n n n 个红色的,白色的,或蓝色的珠子组成的项链,珠子是随意安排的。 这里是 n = 29 n=29 n=29 的两个例子:

第一和第二个珠子在图片中已经被作记号。
图片 A 中的项链可以用下面的字符串表示:
brbrrrbbbrrrrrbrrbbrbbbbrrrrb
假如你要在一些点打破项链,展开成一条直线,然后从一端开始收集同颜色的珠子直到你遇到一个不同的颜色珠子,在另一端做同样的事(颜色可能与在这之前收集的不同)。 确定应该在哪里打破项链来收集到最大数目的珠子。
例如,在图片 A 中的项链中,在珠子 9 9 9 和珠子 10 10 10 或珠子 24 24 24 和珠子 25 25 25 之间打断项链可以收集到 8 8 8 个珠子。
白色珠子什么意思?
在一些项链中还包括白色的珠子(如图片B) 所示。
当收集珠子的时候,一个被遇到的白色珠子可以被当做红色也可以被当做蓝色。
表现含有白珠项链的字符串将会包括三个符号 r,b,w 。
写一个程序来确定从一条被给出的项链可以收集到的珠子最大数目。
输入格式
第一行一个正整数
n
n
n ,表示珠子数目。
第二行一串长度为
n
n
n 的字符串, 每个字符是 r , b 或 w。
输出格式
输出一行一个整数,表示从给出的项链中可以收集到的珠子的最大数量。
样例 #1
样例输入 #1
29
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb
样例输出 #1
11
提示
【数据范围】
对于
100
%
100\%
100% 的数据,
3
≤
n
≤
350
3\le n \le 350
3≤n≤350
题目翻译来自NOCOW。
USACO Training Section 1.1
解析:
一道模拟题,思路是枚举项链每个可能打破的位置,然后计算从该位置向两侧收集到的珠子的数量。
实现逻辑
-
对于每个打破点,可以尝试将白色珠子视作红色或者蓝色,计算两种情况下能够取得的珠子的数量。
-
使用双层循环遍历所有的打破点。
-
对于每个打破点,分别相左和向右收集珠子,并计算总数量。
-
为了方便处理,可将字符串复制 2 2 2 遍,从中间的串开始枚举,如原串为
rbw,将其复制两遍变为rbwrbwrbw,这样在边界情况下依然可以访问到后面的元素。 -
注意最后要对答案和 n n n 取个最小值,因为我们将原串复制了,所以数量可能会大于 n n n。
代码如下:
#include<bits/stdc++.h>
using namespace std;
string s;
int n,ans=-1;
int main() {
cin>>n;
cin>>s;s+=s;s+=s; //复制两遍
for(int i=n;i<2*n;i++) {
int blue=0,red=0,left=-1,right=-1;
//向左侧数蓝色、红色珠子数,取最大值
for(int j=i;j>=i-n;j--) {
if(s[j]=='r') break;
else blue++;
}
for(int j=i;j>=i-n;j--) {
if(s[j]=='b') break;
else red++;
}
left=max(blue,red);
//向右侧数蓝色、红色珠子数,取最大值
blue = 0,red = 0;
for(int j=i+1;j<=i+n;j++) {
if(s[j]=='r') break;
else blue++;
}
for(int j=i+1;j<=i+n;j++) {
if(s[j]=='b') break;
else red++;
}
right = max(blue,red);
ans=max(ans,left+right);
}
ans = min(ans,n); //注意答案不能超过 n
cout<<ans<<endl;
return 0;
}
时间复杂度 O ( n 2 ) O(n^2) O(n2)。

861

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



