P1203 [USACO1.1]Broken Necklace(模拟-枚举)

P1203 [USACO1.1]坏掉的项链Broken Necklace

题目描述

你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的。 这里是 n=29 的二个例子:

在这里插入图片描述
第一和第二个珠子在图片中已经被作记号。

图片 A 中的项链可以用下面的字符串表示:

brbrrrbbbrrrrrbrrbbrbbbbrrrrb

假如你要在一些点打破项链,展开成一条直线,然后从一端开始收集同颜色的珠子直到你遇到一个不同的颜色珠子,在另一端做同样的事(颜色可能与在这之前收集的不同)。
确定应该在哪里打破项链来收集到最大数目的珠子。

例如,在图片 A 中的项链中,在珠子 9 和珠子 10 或珠子 24 和珠子 25 之间打断项链可以收集到8个珠子。

白色珠子什么意思?

在一些项链中还包括白色的珠子(如图片B) 所示。

当收集珠子的时候,一个被遇到的白色珠子可以被当做红色也可以被当做蓝色。

表现含有白珠项链的字符串将会包括三个符号 r , b 和 w 。

写一个程序来确定从一条被给出的项链可以收集到的珠子最大数目。

输入输出格式 d 输入格式: 第 1 行: N, 珠子的数目

第 2 行: 一串长度为N的字符串, 每个字符是 r , b 或 w。

输出格式: 输入输出样例

输入样例#1:

29 
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb
输出样例#1:
11

题目思路

这一题可以用dp去写,但是我只能想到用暴力枚举(由于数据范围比较小)在每一个位置断开所能得到的珠子的最大数量,具体思路直接看代码吧

题解如下

#include<iostream>
using namespace std;
const int Len = 355;

struct Bead
{
    int cnt;
    char color;
}bead[Len];


int main()
{
   // freopen("T.txt","r",stdin);
    int pos = 0;
    int n;
    scanf("%d", &n);

    char ch;
    int cnt = 0;
    int last_ch = '@';      //对上一个初始化成一个特殊字符
    for(int i = 0; i < n; i ++)     //统计连续相同颜色珠子的数量及颜色
    {
        cin>>ch;
        if(ch != last_ch)
        {
            bead[pos].cnt = cnt;
            bead[pos].color = last_ch;
            pos ++;
            cnt = 0;
            last_ch = ch;
        }
        cnt ++;
    }
    //对字符串最后一个连续相同的字符数量进行统计
    bead[0].color = bead[1].color;
    bead[pos].cnt = cnt;
    bead[pos ++].color = last_ch;

    int ans = 0,len = 0;    //len 当前正在讨论从某个位置断开可以得到的最大珠子的数量

    for(int i = 2; i < pos; i ++)   //遍历每一个位置进行讨论
    {
        if(bead[i].color == 'w')
            continue;

        int l_i = i - 2,r_i = i + 1;    //l_i 从i - 2这个位置从右向左遍历,r_i从i+1 这个位置从左向右一个一个的判读
        r_i %= pos;     //防止下标越界

        len = bead[i - 1].cnt + bead[i].cnt;
        int flag_w = 0;             //是否i - 1 这个位置的珠子是白色的
        if(bead[i - 1].color == 'w')    //如果是
        {
            flag_w = 1;
            bead[i - 1].color = bead[l_i].color;    //把i-1这些白颜色的珠子变成 i - 2 位置的珠子的颜色
        }
        char l_co = bead[i - 1].color,r_co = bead[i].color; //l_co 挨着断开出左边珠子的颜色,r_co挨着断开出右边珠子的颜色
        //右边的长度判断
        while(true)
        {
            if(bead[r_i].color == r_co || bead[r_i].color == 'w')
            {
                len += bead[r_i].cnt;
                r_i ++;
                r_i %= pos;
            }
            else
            {
                break;
            }
            if(r_i == l_i)      //在讨论右边长度的时候如果r_i == l_i 时候是没有讨论这个位置所代表的珠子颜色是否 l_co 或 r_co 颜色相同,这将在讨论 左边长度 的时候进行讨论
            {
                break;
            }
        }
        //左边长度的判读
        while(true)
        {
            if(bead[l_i].color == l_co || bead[l_i].color == 'w')
            {
                len += bead[l_i].cnt;
                l_i --;
                if(l_i < 0)
                    l_i = pos - 1;
            }
            else
            {
                break;
            }

            if(l_i == r_i)      //特判了
            {
                if(bead[l_i].color == 'w' || bead[l_i].color == l_co || bead[l_i].color == r_co)
                {
                    len += bead[l_i].cnt;
                }
                break;
            }
        }

        if(flag_w)          //如果i - 1 位置的颜色是白色,用完之后要把这个i - 1 位置所代表的珠子颜色变回来
        {
            bead[i - 1].color = 'w';
        }

        ans = max(ans , len);
    }
    if(ans == 0)        //特殊情况讨论,如果所给珠子串全是 ‘w’
    {
        ans = n;
    }
    printf("%d",ans);

    return 0;
}
发布了84 篇原创文章 · 获赞 120 · 访问量 8651

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/104086437