破损项链中的错误答案问题USACO

时间:2011-03-13 04:51:50

标签: java algorithm

破碎的项链

你有一条N红色,白色或蓝色珠子(3 <= N <= 350)的项链,其中一些是红色的,另一些是蓝色的,其他是白色的,随机排列。以下是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

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

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

假设您要在某个时刻打破项链,将其直接铺设,然后从一端收集相同颜色的珠子,直到达到不同颜色的珠子,并为另一端做同样的事情(可能与此前收集的珠子颜色不同。)

确定项链应该被打破的位置,以便可以收集最多的珠子。

实施例

例如,对于图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

wwwbbrwrbrbrrbrbrwrwwrbwrwrrb | wwwbbrwrbrbrrbrbrwrwwrbwrwrrb

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

                    rrrrrb|bbbbb  <-- assignments

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

                    5+6 = 11 total

这是USACO训练问题我遇到了麻烦;我一直得到错误的答案。 ...请不要告诉我这是愚蠢的或愚蠢的;这没有帮助! :d

9 个答案:

答案 0 :(得分:3)

嘿,我很喜欢这个,但我没有费心去编码。无论如何,我的想法就是这个。

首先,您不需要存储所有珠子颜色(Go Australian拼写!),您只需要存储多少相同颜色的珠子。所以:

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&lt; 350所以即使O(N ^ 3)也应该在1秒内工作。也许2.无论如何,我相信这是O(N ^ 2)所以你应该能够在一秒钟内运行这个程序350次。请评论是否有些令人困惑,因为我不是最好的解释者。快乐的编码。

答案 1 :(得分: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;
}

答案 2 :(得分:1)

这是我的代码:

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){

        }
    }
}

答案 3 :(得分:0)

当你在计算机竞赛中遇到一个奇怪的问题时,它的概率是dynamic programming(Bellman类,而不是Ruby类。)

查看this tutorial

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

答案 4 :(得分:0)

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

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

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]

答案 5 :(得分:0)

很长一段时间我在学习编程的时候做过这个。我只是搜索了我的电脑,找到了我提交的解决方案。我可以提供代码,但一切都搞砸了。 = 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;
}

}

答案 6 :(得分:0)

我使用了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;


 }

答案 7 :(得分:0)

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

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;
    }
}

答案 8 :(得分:-1)

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

这是算法(我通过了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)以白色结尾。所以white可以加入到随后的rw中    另请注意,以下序列永远不会以白色开始 6)对于子序列数组中的每个条目,添加条目k和k + 1的长度 然后从条目k-1中略过白色空格(如果有的话)并添加到上面(因为这是一个圆圈,然后k-1条目可能是数组中的最后一个)。
如果大于最大值,则更改最大值

对于项链中不到三个子序列有一些棘手的问题,但它只是单调乏味,没有诀窍。