USACO Broken Necklace 解题日志

来源:互联网 发布:淘宝上有意思的东西 编辑:程序博客网 时间:2024/06/17 19:42

啊!!这道题花了比我想象中更长的时间!再一次被自己蠢哭。

题目很简单:

Broken Necklace

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 beadsLine 2:a string of N characters, each of which is r, b, or w

SAMPLE INPUT (file beads.in)

29wwwbbrwrbrbrrbrbrwrwwrbwrwrrb

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                             vwwwbbrwrbrbrrbrbrwrwwrbwrwrrb|wwwbbrwrbrbrrbrbrwrwwrbwrwrrb                       ******|*****                       rrrrrb|bbbbb  <-- assignments                   5xr .....#|#####  6xb                        5+6 = 11 total

首先,我本来想像题目中的OUTPUT EXPLANATION一样,把项链“复制”一条接在后面。但发现反正直接用mod N来好像也没太大问题就直接在一条链上面做文章。

然后就是捡珠子的过程了。最开始忽略了white的存在(好吧不是忽略了,是老毛病——一做题就忘了这个条件了),写到一半才发现,于是删掉solve函数重新写。

最容易想到的就是暴力做法吧?但是经过一学期好多题(好吧其实不多)用暴力做法都会超时,我并没有去尝试这个方法,不知在USACO上会不会超时。但是用更快速的算法总是好的是吧?我只学过几个算法,这里正好可以用到我学过的“动态规划”(DP)。说个题外话,我一度认为DP是深度搜索的意思……原因,deep嘛……

言归正传!

这个问题的状态和状态转移方程都一目了然。把项链一刀断开,分成左右两部分,再分别对左右递归即可。这里有个小插曲。一开始,我把左右的数组分别命名为left和right,可是编译老是警告。菜鸟如我还从来没有见过这种情况。然后,突然我发现报错表中出现了一个头文件的名字,原来是iostream的一个头文件里,left和right已经被用了。我突然明白了为什么看到书上表示的左右不直接用left和right了,以前我是认为大家觉得直接打单词很麻烦的。哎!于是我就把数组名字改成了lh和rh。

在我认为可以提交后(我没有自己验证),却老是出错!后来我发现是计算右边时,把i + 1打成了i + 2。可是把这里修改了还是出错。然后就发现,在枚举位置在第0号位的珠子后,整个项链就已经没有白色的珠子了。所以我才弄了个necklace的“分身”necklace1,以便每一次重置。感觉这种方法很傻,希望能知道更好的方法。

把这里修改后,依然错误!我有点悲伤。难道是我的算法哪个地方不对吗?苦苦思索了很久,OMG,本来是i + 2,我手残打成了i + 21。哎,悲伤。

就这样一路坎坷,TASK 1过了。

然而TASK 2错了。数据是rrr,原来是陷入了死循环。悲伤之余立了个flag来判断珠子有没有被捡走。可是,问题出现了,我得出的答案是4,但正确答案是3。为什么呢?我百思不得其解啊,真的,到现在我都不知道为什么(如果有人看到这篇文章并且看出了为什么请告诉我,谢谢!!!)。最后我只好采取了一种有些流氓的方法——当最后结果大于N(珠子总数)后,就直接输出珠子总数——感觉不但流氓,而且傻啊!

于是我就怀着悲伤的心情再次提交,并做好了又出现什么我没有想到的问题的心理准备。不过运气不错,后面的数据都过了。


下面贴上我的代码:


#include<iostream>#include<fstream>#include<string>#include<cstring>using namespace std;int num[400] = {0}, lh[400] = {0}, rh[400] = {0};int haha = 0;int N;bool flag[400] = {0};char necklace[400];char necklace1[400];int sleft(int i){flag[i] = 1;if (necklace1[i] != 'w'){if (necklace1[i] == necklace1[((i - 1) + N) % N] && flag[((i - 1) + N) % N] == 0)lh[i] = sleft(((i - 1) + N) % N) + 1;else if (necklace1[((i - 1) + N) % N] == 'w' && flag[((i - 1) + N) % N] == 0){necklace1[((i - 1) + N) % N] = necklace1[i];lh[i] = sleft(((i - 1) + N) % N) + 1;}else lh[i] = 1;}if (necklace1[i] == 'w'&& flag[((i - 1) + N) % N] == 0){necklace1[i] = necklace1[((i - 1) + N) % N];lh[i] = sleft(((i - 1) + N) % N) + 1;}return lh[i];}int sright(int i){if (flag[i + 1] != 1){flag[i + 1] = 1;if (necklace1[(i + 1) % N] != 'w'){if (necklace1[(i + 1) % N] == necklace1[(i + 2) % N] && flag[(i + 2) % N] == 0)rh[i] = sright((i + 1) % N) + 1;else if (necklace1[(i + 2) % N] == 'w'&& flag[(i + 2) % N] == 0){necklace1[(i + 2) % N] = necklace1[(i + 1) % N];rh[i] = sright((i + 1) % N) + 1;}else rh[i] = 1;}if (necklace1[(i + 1) % N] == 'w' && flag[(i + 2) % N] == 0){necklace1[(i + 1) % N] = necklace1[(i + 2) % N];rh[i] = sright((i + 1) % N) + 1;}}else rh[i] = 0; return rh[i];}int solve(){for (int i = 0; i < N; ++i){for (int j = 0; j < N; ++j)necklace1[j] = necklace[j];memset(flag, 0, sizeof(flag));num[i] = sleft(i) + sright(i);}for (int i = 0; i < N; ++i){if (haha < num[i])haha = num[i];}if (haha > N) haha = N;return haha;}int main(){ifstream fin("beads.in");ofstream fout("beads.out");fin >> N;for (int i = 0; i < N; ++i)fin >> necklace[i];fout << solve() << endl;fin.close();fout.close();return 0;}


0 0