• USACO:Broken Necklace


    思路:看了看像是动态规划中的最大子串,以前做过一个类似的,网上说是用模拟的水题,自己想用动态规划做一做,就试了一试....

    时间:用了3天...每天YY几个小时....

    提交情况:不谈了...

    心得:打代码的时候都把注释给加上,思路比较清晰,只是后来发现思路漏洞逐渐显露出来,太多情况没有注意,导致后面的程序不断修改,很难看!

    坑爹的...........

     

    *****************************************************************************************************************************

    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  *****************************************************************************************************
    AC 代码:
    /*
    ID: jun41821
    PROG: beads
    LANG: C++
    */
    #include <iostream>
    #include <fstream>
    #include <cstring>
    using namespace std;
    int main()
    {            //思路    从头开始枚举,有点动态规划(最大子串)的感觉 试试
        //第一次弄完后  少了圆循环那种情况  只是一个链的枚举  再试
        ofstream fout ("beads.out");
        ifstream fin ("beads.in");
        char s[360];
        int N,i,change,maxn,a,b,j,k,max,fc,c1,c2,c3,q,x;
        fc=c1=c2=c3=0;
        fin>>N;
        fin>>s;
        //结合样例 缺少一种对w处理的方法处理w    /*如bwwr此时断点会设在wr处*/但是下一次计算时  ww没计算入b   在计算b时进行考虑
            max=0;a=0;b=1;maxn=0;
            for(i=1;i<N;i++)
            {
                q=i-1;
                while(s[q]=='w')
                {
                    q--;
                    if(q==0)
                    break;
                }
                if(s[i]=='w'||s[i]==s[i-1]||s[i]==s[q]||s[q]=='w')
                    change=0;
                else  change=1;
             if(change==0)
                 b++;
             if(change==1)               //改变的时候进行一次判断
                {
               //if(fc==1){fc=2;}
                if(fc==0)  {c1=b;fc=1;}//第一次改变  为循环判断做准备                    //maxn为当前的合   与之前的max应区分开来
                    else if(fc==1){c2=b;}           //第二次改变
                     a=maxn-a;            //更新一下a //a为b以前的累计数   此时maxn为先前的maxn  含先去的b
        maxn=maxn+b-a;                            //maxn+上新的b
                    if(maxn>max)                            //当前的maxn与全局max比较
                    {
                        max=maxn;         //得到一个b        若最大改变  记录改变时的地址求得最大  但没地址?
                        k=i-b;//记录地址
                    }
        cout<<"i:"<<i<<endl<<"b:"<<b<<endl<<"max:"<<max<<endl<<"maxn:"<<maxn<<endl<<"a:"<<a<<endl;
                    a=b;c3=b;
        b=1;             //用a记录上一次的b   b重新开始计算  此时改变 b应已记录为1
                    j=i;
                    if(j)
                    while(s[--j]=='w')          //先前在这对i进行了操作 导致死循环..
                            b++;
                            x=b;            //在碰到改变时  用一个处理记录改变前的连续w串的个数 //这才是真实的b
        if(fc==1){c2-=b-1;}
        fc++;          //最后一次改变后  和最后一次改变前
                }
               if(i==N-1)  {c1+=b;c3-=x-1;}
                //直接加入循环当i==N-1时
            }//结束时    b为尾最后一次改变的积累   maxn为上一次断点前的和  a则为上上次断点前的一次累加
            //枚举完毕   //此时   max为最大子串   k则为坐标
            //断点为(k-1)和k之间
            //突然回去看输入.....发现不用找断点....傻逼了,....
            //在最后加一次判断   是否符合圆的那种情况  并记录下去
            // 特殊情况 直接枚举算了...后来发现直接枚举更坑爹.....再后来发现加进去循环判断更更坑爹...
            //初学者伤不起啊..还是枚举算了
            //找到上尾的最后一个断点   再找前的第一个断点
            i=N-1;
            j=0;
            while(s[i]=='w')
            {
                i--;
            }
            while(s[j]=='w')
            {
                j++;
            }
            if(fc==2)
            {
                fout<<N<<endl; return 0;
            }
            else if(s[i]==s[j]||max==0)
            {
                if(c1+c2>max)
                max=c1+c2;                              //最后的判断...
                if(c1+c3>max)
                max=c1+c3;
            }
            cout<<c1<<c2<<c3<<fc;
            fout<<max<<endl;
        return 0;
    }
  • 相关阅读:
    Ruby(1):入门
    html 制作静态页面新知识
    mysql 可视化界面操作指令
    html 基础
    Eclipse导入Java工程导入错误
    shell 25个常用命令
    java JDBC
    java 8新特性 instant
    git
    spring mvc 注解详解
  • 原文地址:https://www.cnblogs.com/amourjun/p/5134209.html
Copyright © 2020-2023  润新知