USACO_CHA1_破碎的项链

废话

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;
}

如果该题解对您有帮助的话,希望您不吝点赞。
欢迎讨论交流,期待共同进步!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值