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 will include 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.
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb wwwbbrwrbrbrrbrbrwrwwrbwrwrrb ****** ***** rrrrrb bbbbb <-- assignments 5 x r 6 x b <-- 11 total
题解:爆搜就行。时间复杂度O(N^2)。先把项链复制一下,然后就转成线性的了。之后枚举断开点,然后向左扫描统计一下,向右也扫描统计一下。如果最后得到的总和大于n,那么说明重复了,也就是说可以全部取出来,直接输出n即可。
1 /* 2 ID:spcjv51 3 PROG:beads 4 LANG:C 5 */ 6 #include<stdio.h> 7 #include<string.h> 8 #define maxlen 750 9 int main(void) 10 { 11 FILE *fin=fopen("beads.in","r"); 12 FILE *fout=fopen("beads.out","w"); 13 char str[maxlen],pre,suc; 14 int i,j,k,m,n,maxinum; 15 fscanf(fin,"%d",&n); 16 maxinum=0; 17 fscanf(fin,"%s",str); 18 for(i=0; i<n; i++) 19 str[n+i]=str[i]; 20 for(i=0; i<2*n; i++) 21 { 22 int l,r; 23 l=0; 24 r=0; 25 k=i; 26 while(str[k]=='w'&&k>0) 27 { 28 k--; 29 l++; 30 } 31 pre=str[k]; 32 j=k; 33 while(j>=0&&(str[j]==pre||str[j]=='w')) 34 { 35 j--; 36 l++; 37 } 38 k=i+1; 39 while(str[k]=='w'&&k<2*n) 40 { 41 r++; 42 k++; 43 } 44 suc=str[k]; 45 j=k; 46 while(j<2*n&&(str[j]==suc||str[j]=='w')) 47 { 48 j++; 49 r++; 50 51 } 52 if((l+r)>maxinum) maxinum=l+r; 53 } 54 if (maxinum>n) maxinum=n; 55 fprintf(fout,"%d\n",maxinum); 56 fclose(fin); 57 fclose(fout); 58 return 0; 59 }
题解2:用动态规划解决。时间复杂度O(n) 。我没用这种方法,直接丢 nocow的题解好了。
这道题用标准的搜索是O(n^2)的,可以用类似动态规划的方法优化到O(n)。
用数组bl,br,rl,rr分别记录在项链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。
(DP+mod):按这个动规的思路,还有另外一种变形,用模运算来处理环
这样初值不能简单地用bl[0]=rl[0]=0来表示,我们没有任何理由认为0位置应当为初始位置(在用模运算处理环的情况下)
应该在项链中找到第一个'b',则此位置的rl,rr都为0,从这个位置按照上面的递归关系进行DP计算rl,rr,如果没有'b',那么整个项链都可看做红色,直接输出n即可。同理,可以计算bl,br以及最后的结果,简洁的C代码已贴在代码页。
事实上不必使用动态规划,直接搜索亦可达到O(n)。
把两个同样的项链放在一块,从头开始用两个变量(变量)a,b记录自左方某点至目前为止可搜集到之两种颜色珠子数,
取途中所出现a+b之最大值,遇颜色变换时再将b指定给a即可,代码十分简洁。