USACO题解——Section 1.2——Broken Necklace

题目地址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=0; j--) {    /*从右到左*/
        计算左边相同字串最大长度
    }
    for (int j=i+1; j

模拟的AC参考代码

/*
ID: your_id_here
PROG: beads
LANG: C++                
*/
//Broken Necklace
//https://train.usaco.org/usacoprob2?a=cjtzbRDL8Yz&S=beads
#include 
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> 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)

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

你可能感兴趣的:(OJ题解,#,USACO题解)