NECKLACE section1.1 个人题解

题目大意

给定一串由三种珠子构成的项链,珠子的种类分为红色的r,蓝色的b,白色的w;
 项链是个圈,按顺序由一串字符表示,如:
               r b b r 1
              r       b 2
             r         r
            r           r
           b             r
 位置3-->                        <--位置2
          w               b
          b               b
          b               b 
                              <--位置1
           r             r 
            b           r
             b         r
               r      r
                 r b r

   用字符串rbrrrbbbrrrrrbrrbbrbbwbrrrrbb表示。
   在项链上挑一个位置剪开,从剪开位置向两端收集连续的且同色的珠子,收集到的珠子总数记为N,求N的最大值。
   如图,在位置1剪开,向两端分别收集到5个红珠子与3个蓝珠子,N1=8;在位置2剪开,向两端分别收集到3个红珠子与三个蓝珠子,N2为6;在位置3剪开,向两端分别收集到3个蓝珠子和1个蓝珠子。
   如果遇到白珠子,则白珠子可以当作红珠子,也可以当作蓝珠子。
输入格式:
line 1:N(表示一串项链上的珠子总数)
line 2:N个字符的字符串(表示这一串珠子)
输出格式
one line:Nmax(表述取得的最大珠子数)
样例输入
29
rbrrrbbbrrrrrbrrbbrbbwbrrrrbb
(如上图)
样例输出
8

题解:

    从结果来看,收集珠子数最大的剪开位置某一端收集到的珠子只可能是红珠子或者蓝珠子(每一个剪开位置都是如此)。同时,最大收集珠子数一定等于左端可收集的最大珠子数加上右端可收集的最大珠子数。

    依据上述前提提出如下算法:任取一个剪开点,假设先从左端开始收集(从右端先开始效果对称),则有两种情况,收集最大可能的红色珠子(情况1)或收集最大可能的蓝色珠子(情况2)(当收集红色珠子时,白色珠子当作红色珠子;同样,当收集蓝色珠子时,白色珠子当作蓝色珠子)。
    在上述两种情况的基础上,又分别有两种情况:右端收集红色珠子(情况11和情况21),右端收集蓝色珠子(情况12和情况22)。
    求得四种情况下的左端收集数与右端收集数之和,取最大的和作为该剪开点下的收集数N。
    遍历所有剪开点,求出所有剪开点下的收集数N,取最大的,即为Nmax。
    需要注意的是:右端取珠子是在左端取珠子的基础上取的,所以右端取珠子需要避免重复取左端已经取过的珠子!
    同时,由于项链为环形,可以考虑用数组读入之后,在原数组后粘贴上同样的一个数组,这样便可以实现在环形条件下取珠子。

代码:

#include<stdio.h>
int max(int a,int b)
{
if(a>b)
    return a;
else
    return b;
}
int min(int a,int b)
{
if(a>b)
    return b;
else
    return a;
}
int main()
{
char bead[400],beads[800];
intlen[800],num,n,lb=0,lr=0,rb=0,rr=0,maxb,
maxr,maxm,i,j;
scanf("%d",&num);
scanf("%s",bead);
n=2*num;
for(i=0;i<num;i++)
{
    beads[i]=bead[i];
    beads[i+num]=bead[i];
}
for(i=0;i<n;i++)
{
    lb=0;
    lr=0;
    rb=0;
    rr=0;
    j=i;
    while(j>=max(0,i-num+1))
    {
        if(beads[j]=='b'||beads[j]=='w')
        {lb++;j--;}
        else
            break;

    }
    j=i+1;
    while(j<min(n,i+num-lb+1))
    {
        if(beads[j]=='b'||beads[j]=='w')
        {rb++;j++;}
        else
            break;
    }
    j=i+1;
    while(j<min(n,i+num-lb+1))
    {
        if(beads[j]=='r'||beads[j]=='w')
        {rr++;j++;}
        else
            break;
    }
    len[i]=max(lb,lr)+max(rb,rr);
}
maxb=len[0];
for(i=0;i<n-1;i++)
{
    if(maxb<len[i])
        maxb=len[i];

}
for(i=0;i<n;i++)
{
    lb=0;
    lr=0;
    rb=0;
    rr=0;
    j=i;
    while(j>=max(0,i-num+1))
    {
        if(beads[j]=='r'||beads[j]=='w')
        {lr++;j--;}
        else
            break;

    }
    j=i+1;
    while(j<min(n,i+num-lr+1))
    {
        if(beads[j]=='b'||beads[j]=='w')
        {rb++;j++;}
        else
            break;
    }
    j=i+1;
    while(j<min(n,i+num-lr+1))
    {
        if(beads[j]=='r'||beads[j]=='w')
        {rr++;j++;}
        else
            break;
    }
    len[i]=max(lb,lr)+max(rb,rr);
}
maxr=len[0];
for(i=0;i<n-1;i++)
{
    if(maxr<len[i])
        maxr=len[i];

}
maxm=max(maxb,maxr);
fprintf(fout,"%d\n",maxm);
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值