废话
USACO TRAINING的网站又进不去了,所以我将刷题网站转到了ACwing。
这个网站上的相关题目是已经经过翻译了的,比较友好。我个人购买了ACwing上y总的USACO TRAINING习题辅导的网课,对刷题很有帮助。
牛课上也可以找到这套题的汉化版,但是个人还是更喜欢ACwing,因为当题目WA掉的时候,他会给出WA了的测试数据。
一、题目描述
链接:https://www.acwing.com/problem/content/1344/
来源:ACwing
你有一条由 N 个珠子串成的项链,珠子的颜色有红、白、蓝三种,珠子在项链中呈随机分布。
例如 N=29 时,两个项链的示例如下所示:
1 2 1 2
r b b r b r r b
r b b b
r r b r
r r w r
b r w w
b b r r
b b b b
b b r b
r r b r
b r r r
b r r r
r r r b
r b r r r w
样例 A 样例 B
r 红珠子
b 蓝珠子
w 白珠子
图片对项链的第一颗珠子和第二颗珠子进行了标记。
样例 A 中的项链只包含蓝红两种颜色的珠子,将所有珠子按顺序记录颜色为:
brbrrrbbbrrrrrbrrbbrbbbbrrrrb
假设你现在要将项链从某个点处断开,并将断开后的项链拉直摆放,然后从一端开始收集相同颜色的珠子,直到碰到另一种颜色的珠子为止,完成后在另一端进行相同的操作(这次收集的珠子的颜色可能与之前收集的颜色并不相同)。
现在,你需要判断在项链的哪一处将项链断开,可以使得我们收集珠子的数量达到最多。
例如,对于样例 A 提供的项链,我们在 9 号珠子和 10号珠子之间断开项链,或者在 24 号珠子和 25 号珠子之间断开项链,可以收集到最多 8 个珠子。
另外,某些项链除蓝红珠子外,还包含白珠子,如样例 B 所示。
收集珠子时,如果我们遇到了白色珠子,那么我们可以将它视为红色或蓝色,并将其涂上相应的颜色。
表示项链的字符串只包含 r,w,b 三种字符。
请你编写一个程序,求出我们可以收集珠子的最大数目。
输入格式
第一行包含整数 N,表示珠子的数量。
第二行包含一个由 N 个字符构成的字符串,字符串中只包含r,w,b 三种字符。
输出格式
共一行,包含一个整数表示我们可以收集珠子的最大数目。
数据范围
3 ≤ N ≤ 350
输入样例:
29
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb
输出样例:
11
二、题解
题目的理解:
项链是一个圈,从不同的点断开向量我们会得到不同的线形项链。从所得线性项链的两端开始取珠子,直至珠子颜色与之前所取颜色不同(白色珠子既可以当作红色也可以当作蓝色)。问这个项链最多能取到多少珠子。
我们在某个位置打断项链是不破坏项链珠子的。也就是说,对于一个长为n的项链,其答案的最大值是n。我一开始理解错了题意,导致WA了一次。
做题思路:
这个题的数据范围是很小的,所以我们可以通过枚举的方法求解。遍历从每一个点断开时形成的线性项链可以取到的珠子个数,取最大值即可。
小技巧:
项链是一个圈,而我们存储的时候存的是一个数组,所以从某点断开后形成的线形项链不方便直接表示。
我们可以在当前数组的尾部再接上一次当前数组。这样,我们从某个点断开后形成的线性项链,就是当前点再向后取n - 1个点。
即,从2号点断开后形成的项链是2 ~ 2+n-1。我们只需遍历0 ~ n-1即可。
三、AC代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n, ans = 0;
int Left, Right;
char Necklace[1000];
int main()
{
int in;
cin >> n;
scanf(" %s", Necklace);
for (int i = 0; i < n; i++)
{
// 在当前数组后再接一个一模一样的数组
Necklace[i + n] = Necklace[i];
}
for (int i = 0; i < n; i++)
{
// 外层循环遍历从哪个点断开
// start、end表示断开后项链的起点和终点
int start = i;
int end = i + n - 1;
// Left和Right分别表示从项链左右端所能取得珠子个数
Left = Right = 0;
// NowColor表示当前已经取过得珠子颜色
char NowColor = 0;
for (int j = start; j <= end; j++)
{
if (NowColor == 0 && Necklace[j] != 'w')
{
NowColor = Necklace[j];
}
else if (NowColor != 0 && Necklace[j] != 'w' && Necklace[j] != NowColor)
{
break;
}
Left++;
}
NowColor = 0;
for (int j = end; j >= start; j--)
{
if (NowColor == 0 && Necklace[j] != 'w')
{
NowColor = Necklace[j];
}
else if (NowColor != 0 && Necklace[j] != 'w' && Necklace[j] != NowColor)
{
break;
}
Right++;
}
ans = max(ans, Left + Right);
}
if (ans > n)
{
// 出现ans > n的情况说明项链不同时包括蓝色和红色珠子
// 在之前计算的时候Left和Right都是n
ans = n;
}
cout << ans << endl;
system("pause");
return 0;
}
如果该题解对您有帮助的话,希望您不吝点赞。
欢迎讨论交流,期待共同进步!