【问题标题】:Incorrect Answer in Broken Necklace Problem USACO [closed]USACO 项链断裂问题中的错误答案 [关闭]
【发布时间】:2011-03-13 04:51:49
【问题描述】:

破碎的项链

你有一条项链,由 N 个红色、白色或蓝色珠子 (3

            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

下面文字中考虑的第一个和第二个珠子已在图片中标出。

图A中的配置可以表示为一串b和r,其中b代表蓝色珠子,r代表红色珠子,如下:brbrrrbbbrrrrrbrrbbrbbbbbrrrrb。

假设你要在某个时候折断项链,把它平放,然后从一端收集相同颜色的珠子,直到你找到一个不同颜色的珠子,然后对另一端做同样的事情(即可能与之前收集的珠子颜色不同)。

确定应该打破项链的点,以便收集最多数量的珠子。

例子

例如,对于图 A 中的项链,可以收集 8 颗珠子,断裂点在珠子 9 和珠子 10 之间,或者在珠子 24 和珠子 25 之间。

如上图 B 所示,在一些项链中包含了白色珠子。收集珠子时,遇到的白色珠子可能会被视为红色或蓝色,然后涂上所需的颜色。表示此配置的字符串将包括三个符号 r、b 和 w。

编写一个程序来确定可以从提供的项链中收集的最大珠子数量。

输入格式

第1行:N,珠数 第 2 行:一串 N 个字符,每个字符为 r、b 或 w

29 wwwbbrwrbrbrrbrbrwrwwrbwrwrrb

输出格式

一行包含可以从提供的项链中收集的最大数量的珠子。

11

输出说明

考虑两个珠子的副本(有点像能够绕着两端跑)。 11的字符串被标记。

            Two necklace copies joined here

wwwbbrwrbrbrrbrbrbrwrwwrbwrwrrb | wwwbbrwrbrbrrbrbrwrwwrbwrwrrb

                    ******|*****

                    rrrrrb|bbbbb  <-- assignments

                5xr .....#|#####  6xb

                    5+6 = 11 total

这是我遇到的 USACO 培训问题;我不断得到不正确的答案。 ...请不要告诉我这是愚蠢或愚蠢的;这没有帮助! :D

【问题讨论】:

  • 看起来很简单,简单的天真是计算游程长度,然后找到最高的游程总和。不要忘记考虑只有一种颜色的项链。我记得为 USACO 这样做是比较容易的问题之一
  • 只要连续选择两个最大的对就足够了(值是颜色出现的次数),作为介绍,w 就足够做简单的额外工作了,我想你可以想出这个。跨度>
  • 我想知道这算作家庭作业吗?

标签: java algorithm


【解决方案1】:

嘿,我已经完成了这个,但我没有费心去编写它。无论如何,我的想法是这样的。

首先,您不需要存储所有珠子的颜色(使用澳大利亚拼写!),您只需要存储一行中相同颜色的珠子的数量。所以对于:

RRBBBWRR

你只需要存储:

2R 3B 1W 2R

需要注意的一点是,如果结尾珠子和起始珠子的颜色相同,您必须考虑到这一点,所以

RRBBBRR

应该存储为

4R 3B
or
3B 4R

同样的事情。请注意,这样做的原因不是为了节省内存或其他任何东西,而是为了确保彼此相邻的珠子是不同的颜色。我们通过组合相同颜色的珠子来做到这一点。

接下来是您逐一检查:
- 如果它是红色的,则将所有的相加,直到找到蓝色,然后继续添加,直到找到另一个红色
- 如果它是蓝色的,除了颠倒之外,做类似的事情
- 如果它是白色的,那么下一个珠子将是红色或蓝色。除了添加白色珠子的数量外,按上述操作

这里有一些例子。 | 序列开始和结束的标记。

B|RB|R

我们找到一个 R 然后是一个 B 然后是另一个 R。因此我们必须在 B 处停下来。在

B|RWRB|R

我们找到了一个 R,然后又找到了一个 R,但我们还没有找到 B,所以我们继续。然后我们找到一个 B,然后找到另一个 R。这一次,既然我们找到了一个 B,我们就必须停下来。

B|RBW|R

我们找到一个 R,然后是一个 B,但我们可以继续,因为下一个是 W,然后我们找到另一个 R,所以我们必须停止。在

B|WRBWB|R

我们数 W,然后找到 R。因此,我们继续直到找到 B,然后继续直到找到另一个 R。这样

B|WBRWR|B

是相反的情况。

现在您所要做的就是实现它:D。当然,这并没有考虑 R、B 和 W 中珠子的实际数量,只是单珠子序列的示例。您必须检查所有可能的序列。您还必须注意从后到头的序列。

最后,你可能会注意到这个算法有时很浪费,但 N 。如果有什么令人困惑的地方,请发表评论,因为我不是最好的解释者。编码愉快。

【讨论】:

    【解决方案2】:
    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    
    int main(){
        int numBeads;
        char temp1[705];
        char temp2[705];    
    
        int i,j,k,lim;
    
        int count1 = 0;
        int count2 = 0;
        int maxcount1 = 0;
    
        char virgin = ' ';
        bool flag = false; //flag == true if  virgin doesn't match
    
        FILE* fin  = fopen("beads.in","r");
        FILE* fout = fopen("beads.out","w");
    
        fscanf(fin,"%d",&numBeads);
        fscanf(fin,"%s",temp1);
    
        strcpy(temp2,temp1);
        strcat(temp1,temp2);
    
        for(i=0,j=numBeads-1;i<numBeads;i++,j++){
            count1 =0;
            count2 = 0;
            flag = false;
            virgin = ' ';
            for(k=i;flag==false && k < (i+numBeads);k++){
                if(temp1[k]=='w'){
                    count1++;
                }
                else if(temp1[k]=='r'){
                    if(virgin==' '){
                     virgin = 'r';               
                    }
                    if(virgin=='r')
                        count1++;
                    else{
                        flag = true;        
                        k--;
                    }
                }
                else if(temp1[k]=='b'){
                    if(virgin==' '){
                     virgin = 'b';               
                    }
                    if(virgin=='b')
                        count1++;
                    else{
                        flag = true;        
                        k--;
                    }
                }
            }
    
            /* Block 2*/
            lim = k;
            flag = false;
            virgin = ' ';       
            for(k=j;flag==false && k < (j+numBeads) && k>=lim;k--){
                if(temp1[k]=='w'){
                    count2++;
                }
                else if(temp1[k]=='r'){
                    if(virgin==' '){
                     virgin = 'r';               
                    }
                    if(virgin=='r')
                        count2++;
                    else{
                        flag = true;        
                        k--;
                    }
                }
                else if(temp1[k]=='b'){
                    if(virgin==' '){
                     virgin = 'b';               
                    }
                    if(virgin=='b')
                        count2++;
                    else{
                        flag = true;        
                        k--;
                    }
                }
            }
            if(maxcount1 < (count1+ count2))maxcount1 = count1 + count2;
        }
    
        fprintf(fout,"%d\n",maxcount1);
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      这是我的代码:

      import java.io.BufferedReader;
      import java.io.BufferedWriter;
      import java.io.FileReader;
      import java.io.FileWriter;
      import java.io.PrintWriter;
      
      /**
       *
       * @author Bansari
      */
      public class beads {
          public static void main(String args[]){
          try{
              BufferedReader f = new BufferedReader(new FileReader("beads.in"));
                                                            // input file name goes above
              PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("str.txt")));
              int len = Integer.parseInt(f.readLine());
              String s=f.readLine();
              int c1=0,c2=0;
              int breakpoint=0;
              int max = 0;
      
              for(int i = 1;i<=len;i++){
      
                  char before = s.charAt((i-1)%len);
                  char after = s.charAt(i%len);
      
                  if(before != after){
                      c1=0;
                      c2=0;
                      int index = i-1;
                      while(s.charAt(index)==before || s.charAt(index)=='w'){
                          char sc = s.charAt(index);
                          c1++;
                          if(index==0)
                              index = len-1;
                          else
                              index--;
                      }
                      index = i;
                      while(s.charAt(index%len)==after || s.charAt(index%len)=='w'){
                          c2++;  
                          if(index == len-1)
                              index = 0;
                          else
                              index++;
                      }
                      if(max < (c1 + c2)){
                          breakpoint=i;
                          max = c1+c2;
                      }
                  }
              }
              out.println(max);
              out.close();
              System.exit(0);
              }catch(Exception e){
      
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        当你在计算竞赛中遇到一个奇怪的问题时,很有可能是dynamic programming(Bellman 类型,而不是 Ruby 类型。)

        看看this tutorial

        动态规划的基本思想是通过回答小子问题来构建“大”答案。我的第一个直觉想法是考虑越来越长的项链,从一个珠子开始,但老实说,我并不是特别擅长动态编程问题。 (我还注意到,在现实世界中遇到 DP 问题最常见的地方是计算奥林匹克竞赛和计算机科学课程中的问题集。)

        【讨论】:

        • 这个问题很简单,我认为不需要动态编程。你必须存储的值的最大数量小于 350,天真已经是 O(n)
        • 动态编程和临时编程问题之间没有关联。你只需要做足够多的动态编程练习,然后就和其他的一样了。
        • +1 因为它让我想起了一句话,如果你的主要工具是锤子,那么一切看起来都像钉子。现在,如果其他人也赞赏这将回到 0 :-)
        • 啊,他们真的很讨厌你这个人(或者讨厌动态编程),对不起!我的 +1 被掩盖了。
        • 不用担心,我可以承受一些反对票,并且考虑到我被提出 DP 问题的次数,从博士比赛到编程竞赛,要么他们错了,要么我的运气一直真的糟糕。
        【解决方案5】:

        撤回 -- 这是错误的,因为它不考虑白珠。

        我可以看到比接受的答案更简单的答案,或者解释太复杂。这是伪代码中的算法(忽略所有相同颜色的情况):

        p = position of first bead of different color than bead 0
        create array of run-lengths: r={5,15,2,9,13}
        create array of sums of adjacents s={20,17,11,22,18} (wrap last)
        find index, k, in s[] of max sum: here it is s[3]
        position = p + r[0] + r[1] + ... + r[k]
        

        【讨论】:

        • 什么是[],如果你有白珠会发生什么?例如,如果有 BWRWRWBWBR 之类的东西,它会做什么?
        • 对于 BWRWRWBWBR,解决方案是在任何地方打破以从每一端获得 1 个珠子,因此我的解决方案提供的任何数字都足够好
        • 我错了 - 我需要彻底阅读问题!
        【解决方案6】:

        很久以前我在学习编程时就这样做了。我刚刚搜索了我的计算机并找到了我提交的解决方案。我可以提供代码,但它都搞砸了。 =P

        import java.io.BufferedReader;
        import java.io.BufferedWriter;
        import java.io.FileNotFoundException;
        import java.io.FileReader;
        import java.io.FileWriter;
        import java.io.PrintWriter;
        
        
        
        
        
        
        public class beads {
        
        /**
         * @param args
         * @throws Exception 
         */
        public static void main(String[] args) throws Exception {
            // TODO Auto-generated method stub
            new beads().go();
        }
        
        private void go() throws Exception {
            // TODO Auto-generated method stub
            BufferedReader bin = new BufferedReader(new FileReader("beads.in"));
            PrintWriter pout = new PrintWriter(new BufferedWriter(new FileWriter("beads.out")));
        
            int count = Integer.parseInt(bin.readLine());
            String beads = bin.readLine();
            int ans = compute(beads);
        
            pout.println(ans);
            pout.close();
        }
        
        private int compute(String beads) {
            // TODO Auto-generated method stub
            int length = beads.length();
            int maxbeads = 0;
            for(int i = 0; i < length; i++){
                int left = 0;
                int right = 0;
                left = computeLeft(beads,i);
                if(left == length){ maxbeads = left; break;}
                right = computeRigtht(beads,i);
                if(right == length){ maxbeads = right; break;}
                if((left+right) > maxbeads) maxbeads = left+right;
                if(maxbeads == length) break;
        
        
            }           
            return maxbeads;
        }
        
        private int computeLeft(String beads, int i) {
            // TODO Auto-generated method stub
            int l = beads.length();
        
            int j = i;
            int count = 0;
            char ch = beads.charAt(i);
            for(; j >=0; j--){
                if(ch == 'w'){//Didnt notice this kind of case before
                    ch = beads.charAt(j);
                    count++;
                }
                else if(beads.charAt(j) == ch || beads.charAt(j)== 'w'){
                    count++;
                }
                else break;
            }
            if(j < 0) j = l-1;
            for(; j > i; j--){
                if(beads.charAt(j) == ch || beads.charAt(j)== 'w'){
                    count++;
                }
                else break;
            }
        
            return count;
        }
        
        private int computeRigtht(String beads, int i) {
            // TODO Auto-generated method stub
            int l = beads.length();
            int j = 0;
            if(i == l-1) j = 0;
            else j = i+1;
            int k = j;
            int count = 0;
            int ch = beads.charAt(j);
            for(; j <l; j++){
                if(ch == 'w'){
                    ch = beads.charAt(j);
                    count++;
                }
                else if(beads.charAt(j)== ch || beads.charAt(j)=='w'){
                    count++;
                }
                else break;
            }
            if(j == l) j = 0;
            for(; j < k-1; j++){
                if(beads.charAt(j) == ch || beads.charAt(j)== 'w'){
                    count++;
                }
                else break;
            }
        
        
            return count;
        }
        

        }

        【讨论】:

          【解决方案7】:

          我使用了 quasiverse 的算法并解决了它。 USACO 服务器已关闭,我无法在他们的判断上对其进行测试,但我想我已经解决了。

           #include<iostream>
           #include<fstream>
           #include<string>
           #include<cstring>
           #include<cstdlib>
          
           #define MAXLEN 350
          
           using namespace std;
          
          
          
           ofstream fout ("beads.out");
          
          
           typedef struct node
           {
               char color;
               int times;
               int lenMax;
               struct node* next;
           } nodeList;
          
           nodeList * getnode()
           {
               nodeList* temp=(nodeList*) malloc (sizeof(nodeList));
               temp->next=NULL;
               temp->lenMax=0;
               return temp;
           }
          
          
          
           void append(nodeList **head,char  tColor,int m)
           {
               nodeList *p=NULL,*newNode=NULL;
               newNode =getnode();
               newNode->color=tColor;
               newNode->times=m;
               newNode->lenMax=0;
               if(*head==NULL)
               {
                   *head=newNode;
                   return;
               }
          
               p=*head;
          
               while(p->next)
                   p=p->next;
          
               p->next=newNode;
          
           }
          
           void shiftNodes(nodeList **head)
           {
               int mon=0;
               nodeList *last=NULL,*p=NULL,*t=NULL;
          
               p=*head;
               do
               {
                   //cout<<p->color<<" "<<p->times<<endl;
                   last=p;
                   p=p->next;
               }
               while(p!=NULL);
               p=*head;
               last->next=*head;
          
               t=*head;
               do
               {
                   if(((*head)->color=='w' || (last)->color=='w' ) || (*head)->color==last->color)
                   {
                       (*head)=(*head)->next;
                       last=last->next;
                   }
                   else if((*head)->color!=last->color )
                   {
                       break;
                   }
                   p=p->next;
               }
               while(p!=t);
          
           }
           void computeLenMaxB(nodeList ** head)
           {
               nodeList *p =NULL,*t=NULL,*s=NULL;
               t=p=*head;
          
               bool gotR=false;
               int tempLenMax=0;
               do
               {
                   if(p->color=='b' && gotR){
                       break;
                   }
                   else if(p->color=='b' && !gotR){
                       tempLenMax+=p->times;
                   }
          
                   else if(p->color=='r' && !gotR){
                       tempLenMax+=p->times;
                       gotR=true;
                   }
                   else if(p->color=='r' && gotR){
                       tempLenMax+=p->times;
                   }
                    else if(p->color=='w' ){
                       tempLenMax+=p->times;
                   }
          
          
                   p=p->next;
               }
               while(p!=t);
               (*head)->lenMax=tempLenMax;
           }
          
           void computeLenMaxR(nodeList ** head)
           {
               nodeList *p =NULL,*t=NULL,*s=NULL;
               t=p=*head;
               bool gotR=false;
               int tempLenMax=0;
               do
               {
                   if(p->color=='r' && gotR){
                       break;
                   }
                   else if(p->color=='r' && !gotR){
                       tempLenMax+=p->times;
                   }
          
                   else if(p->color=='b' && !gotR){
                       tempLenMax+=p->times;
                       gotR=true;
                   }
                   else if(p->color=='b' && gotR){
                       tempLenMax+=p->times;
                   }
                    else if(p->color=='w' ){
                       tempLenMax+=p->times;
                   }
          
          
                   p=p->next;
               }
               while(p!=t);
               (*head)->lenMax=tempLenMax;
           }
          
          
           void fillLenMax(nodeList ** head)
           {
               nodeList *p =NULL,*t=NULL,*s=NULL;
               t=p=*head;
               int wBeads=0;
               do
               {
                   s=p;
                   if(p->color=='b')
                   {
                       computeLenMaxB(&p);
                   }
                    else  if(p->color=='r')
                    {
                        computeLenMaxR(&p);
                    }
          
                    else  if(p->color=='w')
                    {
                        if(p->next->color=='b'){
                           computeLenMaxB(&p);
                        }
                        else if(p->next->color=='r'){
                           computeLenMaxR(&p);
                        }
                    }
                   p=p->next;
               }
               while(p!=t);
          
          
           }
          
           int calcMaxLenMax(nodeList *head)
           {
               nodeList *p=NULL;
               p=head;
               int max=0;
               do
               {
                   //fout<<p->color<<" "<<p->times<<" "<<p->lenMax<<endl;
                   max=(max>p->lenMax)?max:p->lenMax;
                   p=p->next;
               }
               while(p!=head);
               return max;
           }
          
           int main()
           {
               ifstream fin ("beads.in");
          
               char  necklace[MAXLEN];
               int i,j,max;
          
               fin>>necklace;
          
               nodeList* list=NULL;
               int repeat = 0;
               i=0;
               while(i<strlen(necklace))
               {
                   repeat = 0;
                   for(j=i; necklace[j]==necklace[i]; j++)
                   {
                       repeat++;
                   }
          
                   append(&list ,necklace[i],repeat);
                   i=i+repeat;
          
               }
          
               shiftNodes(&list);
          
               fillLenMax(&list);
          
               max=calcMaxLenMax(list);
          
               fout<<max<<endl;
          
               return 0;
          
          
           }
          

          【讨论】:

            【解决方案8】:

            这是一个旧线程,但可能对学习编程的人有用。这是一个使用蛮力的简单解决方案。这个想法是我们通过数据来计算颜色。在第二个循环中,我们对左右部分的和进行成对比较。代码应该易于理解:

            import java.io.*;
            import java.util.LinkedList;
            import java.util.List;
            import java.util.TreeSet;
            
            public class beads {
            
                public static void main(String[] args) throws IOException {
                    BufferedReader f = new BufferedReader(new FileReader("beads.in"));
                    PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("beads.out")));
                    f.readLine();//length
                    String s1 = f.readLine();
                    List<String> counts = new LinkedList<String>();
                    char[] colors = (s1.concat(s1)).toCharArray();
                    char previousColor = ' ';
                    int count = 0;
                    for (char color : colors) {
                        if (previousColor != color && count > 0) {
                            counts.add(count + "-" + previousColor);
                            count = 0;
                        }
                        count++;
                        previousColor = color;
                    }
            
                    if (counts.isEmpty()) {//special case when there is only one color
                        out.println(count/2);
                        out.close();
                        System.exit(0);
                    }
                    TreeSet<Integer> result = new TreeSet<Integer>();
                    for (int i = 1; i < counts.size(); i++) {
                        if(counts.get(i).split("-")[1].charAt(0)=='w')continue;
                        int left = getLeft(counts, i);
                        int right = getRight(counts, i);
                        result.add((left+right));
                    }
                    out.println(result.last());
                    out.close();
                    System.exit(0);
                }
            
                private static int getLeft(List<String> counts, int i) {
                    char start = counts.get(i - 1).split("-")[1].charAt(0);
                    boolean doContinue = true;
                    int count = 0;
                    while (doContinue) {
                        String[] s = counts.get(--i).split("-");
                        char color=s[1].charAt(0);
                        if(start=='w' && color!='w')start=color;
                        boolean incr = (color == 'w' || color==start);
                        if(incr)
                            count += Integer.parseInt(s[0]);
                        else doContinue=false;
            
                        doContinue = doContinue && i > 0;
                    }
                    return count;
                }
            
            
                private static int getRight(List<String> counts, int i) {
                    char start = counts.get(i).split("-")[1].charAt(0);
                    boolean doContinue = true;
                    int count = 0;
                    while (doContinue) {
                        String[] s = counts.get(i).split("-");
                        char color=s[1].charAt(0);
                        if(start=='w' && color!='w')start=color;
            
                        boolean incr = (color == 'w' || color == start);
                        if(incr)
                            count += Integer.parseInt(s[0]);
                        else doContinue=false;
            
                        doContinue = doContinue && ++i < counts.size()-1;
                    }
                    return count;
                }
            }
            

            【讨论】:

              【解决方案9】:

              这是一个预告片!每次解决方案都是如此,如此接近! 同时,白色的珠子是黑色绝望的原因。

              这是算法(我通过了 Usaco 分级机)
              1)找到第一个彩色珠子。说它在 n 珠项链的位置 k
              2)重新排列项链:将0-k部分移动到最后,所以它以真彩色开始。 例如 {wwbrwbrb{ 变成 {brwbrbww}
              3) 将项链切割成多个子部分(字符串阵列),以便每个部分以颜色开头,例如{b rw b r bww}
              4)如果第一段和最后一段颜色相同,则加入它们
              例如{b rw bw rw bww} 变为 {bwwb rw bw rw}(保留序列)
              5) 注意!!!!倒数第二个元素 (bw) 以白色结尾。所以白色可以连接到后面的 rw。
              另请注意,以下序列永远不会以白色开头。
              6) 为子序列数组中的每个条目添加条目 k 和 k+1 的长度。
              然后从条目 k-1 中略去空格(如果有)并添加到上面(因为这是一个圆圈,所以 k-1 条目可能是数组中的最后一个)。
              如果大于最大值,则更改最大值。

              对于项链中少于三个子序列的计算有一些棘手的问题,但这很乏味,没有任何技巧。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-11-29
                • 2010-10-16
                • 1970-01-01
                • 2010-11-16
                • 1970-01-01
                相关资源
                最近更新 更多