USACO题解——Section 1.2——Broken Necklace

解析USACO竞赛中的珠子项链问题,探讨如何通过动态规划或模拟算法找到可收集最多珠子的断点,包括算法思路、优化方法及代码实现。

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

题目地址https://train.usaco.org/usacoprob2?a=ddY7pfROLpX&S=beads

或者我的OJ,http://47.110.135.197/problem.php?id=5186

题目

You have a necklace of N red, white, or blue beads (3<=N<=350) some of which are red, others blue, and others white, arranged at random. Here are two examples for 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
            Figure A                         Figure B
                        r red bead
                        b blue bead
                        w white bead

The beads considered first and second in the text that follows have been marked in the picture.

The configuration in Figure A may be represented as a string of b's and r's, where b represents a blue bead and r represents a red one, as follows: brbrrrbbbrrrrrbrrbbrbbbbrrrrb .

Suppose you are to break the necklace at some point, lay it out straight, and then collect beads of the same color from one end until you reach a bead of a different color, and do the same for the other end (which might not be of the same color as the beads collected before this).

Determine the point where the necklace should be broken so that the most number of beads can be collected.

Example

For example, for the necklace in Figure A, 8 beads can be collected, with the breaking point either between bead 9 and bead 10 or else between bead 24 and bead 25.

In some necklaces, white beads had been included as shown in Figure B above. When collecting beads, a white bead that is encountered may be treated as either red or blue and then painted with the desired color. The string that represents this configuration can include any of the three symbols r, b and w.

Write a program to determine the largest number of beads that can be collected from a supplied necklace.

PROGRAM NAME: beads

INPUT FORMAT

Line 1:N, the number of beads
Line 2:a string of N characters, each of which is r, b, or w

SAMPLE INPUT (file beads.in)

29
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb

OUTPUT FORMAT

A single line containing the maximum of number of beads that can be collected from the supplied necklace.

SAMPLE OUTPUT (file beads.out)

11

OUTPUT EXPLANATION

Consider two copies of the beads (kind of like being able to runaround the ends). The string of 11 is marked.

                Two necklace copies joined here
                             v
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb|wwwbbrwrbrbrrbrbrwrwwrbwrwrrb
                       ******|*****
                       rrrrrb|bbbbb  <-- assignments
                   5xr .....#|#####  6xb
                        5+6 = 11 total

题目分析

题目意思

在一串项链中,从第 i 个位置开始,向左和向右找出颜色为 r 和颜色为 b 的珠子构成的最长字串长度。

算法归类

看到最长,也就是极值,那就是动态规划。

但是由于本题的数据量小,3\leqslant N \leqslant 350,纯粹模拟也可以解决。

数据范围

3\leqslant N \leqslant 350

坑点

1、项链是环形的,但我们只要把两个同样的项链放在一块,就把它转换成线性的了。

2、w的珠子可以任意变色。

3、最长字串长度都不可能超过给的字符串。也就是输出的结果最大值不会超过 N。我在这里卡了好久。

算法思路

模拟

最简单的思路,就是从第 i 个位置开始,从右到左(i-1 到 0)查找相同字串长度,从左到右(i+1 到 n)查找相同字串长度。

for (int i=0; i<n-1; i++) { /**/
    if (data[i]==data[i+1]) {
        //字符相同不处理
        continue;
    }
    将rw变成rb
    将wb变成rb
    将bw变成br
    将wr变成br
    for (int j=i; j>=0; j--) {    /*从右到左*/
        计算左边相同字串最大长度
    }
    for (int j=i+1; j<n; j++) {    /*从左到右*/
        计算右边相同字串最大长度
    }
    更新最大长度数据
}

模拟的AC参考代码

/*
ID: your_id_here
PROG: beads
LANG: C++                
*/
//Broken Necklace
//https://train.usaco.org/usacoprob2?a=cjtzbRDL8Yz&S=beads
#include <bits/stdc++.h>
using namespace std;

/*
8
rrwwwwbb
*/
const int MAXN = 350*2 + 2;
char data[MAXN] = {};

int main() {
    freopen("beads.in", "r", stdin);
    freopen("beads.out", "w", stdout);

    //读入n
    int n;
    cin >> n;

    int i, j;
    for (i=0; i<n; i++) {
        cin >> data[i];
        data[n+i] = data[i];
    }

    int ans = 0;
    for (i=0; i<2*n-1; ) {
        //从第i个开始分。
        if (data[i]==data[i+1]) {
            i++;
            continue;
        }

        //向前找
        int t0 = 1;
        int t1 = 1;
        char ch0 = data[i];
        char ch1 = data[i+1];
        if ('w'==ch0) {
            if ('r'==ch1) {
                ch0 = 'b';
            } else {
                ch0 = 'r';
            }
        } else if ('w'==ch1) {
            if ('r'==ch0) {
                ch1 = 'b';
            } else {
                ch1 = 'r';
            }
        }
        for (j=i-1; j>=0; j--) {
            if (data[j]==ch0 || 'w'==data[j]) {
                t0++;
            } else {
                break;
            }
        }

        //向后找
        for (j=i+2; j<2*n; j++) {
            if (data[j]==ch1 || 'w'==data[j]) {
                t1++;
            } else {
                break;
            }
        }
        i = j-1;

        if (t0+t1>ans) {
            ans = t0+t1;
        }
    }

    if (0==ans) {
        ans = n;
    }
    cout << min(ans, n) << endl;

    fclose(stdin);
    fclose(stdout);

    return 0;
}

模拟优化

在上面的算法中,我们可以看到时间复杂度还是有些高的O(n*m),我们可以优化成O(n)

用数组bl(blue left),br(blue right),rl(red left),rr(red right)分别记录在项链i处向左向右收集的蓝色红色珠子数。

我们只要求出bl,br,rl,rr,那么结果就是max(max(bl[i],rl[i])+max(br[i+1],rr[i+1])) (0<=i<=2*n-1)。

我们以求bl,rl为例:

初始时bl[0]=rl[0]=0。

我们从左往右计算

如果necklace[i]='r',rl[i]=rl[i-1]+1,bl[i]=0;

如果necklace[i]='b', bl[i]=bl[i-1]+1,rl[i]=0;

如果necklace[i]='w',bl[i]=bl[i-1]+1,rl[i]=rl[i-1]+1。

同理可以求出br,rr。

这样我们就将时间复杂度优化为O(n)

优化的代码和动态规划思路过几天再写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值