USACO-Section1.1 Broken Necklace

这篇博客详细介绍了2017年5月25日USACO比赛Section1.1的题目Broken Necklace,包括题目的大意、样例输入和输出,以及解题思路和完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2017-05-25

题目大意:
你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的。 这里是 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 , b 和 w 。
写一个程序来确定从一条被给出的项链可以收集到的珠子最大数目。
样例输入:
29 
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb
样例输出:
11
题解:
因为珠子是圆环,因此将其在1位置切开并在首尾各加一串一样的珠子。然后开始尝试len - 1中切法,每一种切法又分为切口左右两边都不是'w'和左右两边有'w'的情况。然后分别查找两边最长的符合条件的串长。
代码:
    #include<iostream>
    #include<fstream>
    #include<cstring>
    using namespace std;
    int main(){
        ofstream cout("beads.out");
        ifstream cin("beads.in");
        char ch[1500];
        char c[360];
        int len;
        cin >> len;
        cin >> c;
        int len1,len2,tmp1,tmp2;
        int maxlen = 0;
        char flag1,flag2; //记录从切口往两边走遇到的第一个有颜色的珠子颜色
        for(int i = 0;i < len;i++){ //两边分别加了一串相同的珠子
            ch[i] = c[i];
            ch[len + i] = c[i];
            ch[2*len + i] = c[i];
        }
        for(int i = len;i <= 2 * len;i++){ // 尝试len - 1种切法
            tmp1 = i - 1;
            tmp2 = i;
            len1 = 0;
            len2 = 0;
            flag1 = ch[i - 1];
            flag2 = ch[i];
            if(flag1 == 'w'){ //如果遇到的珠子是白色,则需要从找标记颜色
                while(tmp1 >= 0 && ch[tmp1] == 'w'){
                    tmp1--;len1++;
                }
                flag1 = ch[tmp1];
            } 
            while(ch[tmp1] == flag1 || ch[tmp1] == 'w'){ //确认标记后,找最长的符合要求的串长
                tmp1--;
                len1++;
            }
            if(flag2 == 'w'){
                while(tmp2 <= 3 * len && ch[tmp2] == 'w'){
                    tmp2++;len2++;
                }
                flag2 = ch[tmp2];
            } 
            while(ch[tmp2] == flag2 || ch[tmp2] == 'w'){
                tmp2++;
                len2++;
            } 
            if((len1+len2) <= len) 
                maxlen = max(maxlen , (len1 + len2));
            else // 如果两边长度加起来超过原来珠子的长度,答案就直接是原来珠子的长度
                maxlen = len;
        }
        cout << maxlen << endl;
        return 0;
    } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值