可以改进解决方案吗?

时间:2018-05-03 08:53:20

标签: java algorithm

问题陈述

  

这是Byteland美丽的公主桑奇的结婚日。   她的未婚夫克里希纳计划给她一条很棒的红宝石项链。   Krishna目前有蓝色红宝石,g-绿色红宝石,红色红宝石   和y黄色红宝石。他必须将红宝石排列在一起   在一条直线上制作项链。但是,有几个   制作这条项链时应遵循的规则:

     
      
  • 蓝宝石后面应该是蓝宝石或红宝石
  •   
  • 绿宝石后面应该是绿宝石或黄宝石
  •   
  • 红宝石后面应该是绿宝石或黄宝石
  •   
  • 黄色红宝石后面应该是蓝宝石或红宝石
  •   
  • 如果有可能,我们应该始终开始一条蓝色或红色红宝石项链
  •   
     

你能说出项链的最大长度是多少吗?   克里希纳可以做。项链的长度是红宝石的数量   它

     

输入格式

     
      
  • 第一行包含一个表示b。
  • 的整数   
  • 第二行包含表示r。
  • 的整数   
  • 第三行包含一个表示y的整数。
  •   
  • 第四行包含表示g。
  • 的整数   
     

约束

     
      
  • 0 <= b,r,y,g <= 2000
  •   
  • b,r,y,g中的至少一个大于0
  •   
     

输出格式

     
      
  • 单个整数,是问题的答案。
  •   
     

示例TestCase 1

Input
1
1
1
0
Output
3

我的解决方案:

package ruby;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class CandidateCode {

public static void main(String[] args) {
    try {
        BufferedReader br = new BufferedReader(new 
InputStreamReader(System.in));
        Integer b = new Integer(br.readLine());
        Integer r = new Integer(br.readLine());
        Integer y = new Integer(br.readLine());
        Integer g = new Integer(br.readLine());

        if (b + r + y + g > 0 && b <= 2000 && b <= 2000 && r <= 2000 && 
g <= 2000 && y <= 2000 && b >= 0 && r >= 0
                && g >= 0 && y >= 0) {

            ArrayList<Character> necklace = new ArrayList<Character>();
            CandidateCode rn = new CandidateCode();
            int length = rn.calculateLengthofNecklace(b, r, y, g, 
necklace);
            System.out.println(length);
        }
    } catch (Exception e) {
    }

}

private int calculateLengthofNecklace(Integer b, Integer r, Integer y, Integer g, ArrayList<Character> necklace) {
    if (anyRemaining(b))
        necklace = addBlue(b, r, y, g, necklace);
    else if (anyRemaining(r))
        necklace = addRed(b, r, y, g, necklace);
    else if (anyRemaining(g))
        necklace = addGreen(b, r, y, g, necklace);
    else if (anyRemaining(y))
        necklace = addYellow(b, r, y, g, necklace);
    // System.out.println("necklace :" + necklace.toString());
    return necklace.size();
}

private ArrayList<Character> addRed(Integer b, Integer r, Integer y, Integer g, ArrayList<Character> necklace) {
    char lastruby = necklace.size() > 0 && necklace.get(necklace.size() - 1) != null
            ? necklace.get(necklace.size() - 1) : 'z';
    if (anyRemaining(r) && (lastruby == 'y' || lastruby == 'b' || lastruby == 'z')) {
        necklace.add('r');
        r = r - 1;
        // System.out.println("in addRed\n b:" + b + " r: " + r + " y: " + y
        // + " g: " + g);
    } else {
        return necklace;
    }
    ArrayList<Character> n1 = new ArrayList<Character>(necklace);
    ArrayList<Character> n2 = new ArrayList<Character>(necklace);
    n1 = addGreen(b, r, y, g, n1);
    n2 = addYellow(b, r, y, g, n2);
    necklace = n1.size() > n2.size() ? n1 : n2;
    return necklace;

}

private ArrayList<Character> addYellow(Integer b, Integer r, Integer y, Integer g, ArrayList<Character> necklace) {
    char lastruby = necklace.size() > 0 && necklace.get(necklace.size() - 1) != null
            ? necklace.get(necklace.size() - 1) : 'z';
    if (anyRemaining(y) && (lastruby == 'r' || lastruby == 'g' || lastruby == 'z')) {
        necklace.add('y');
        y = y - 1;
        // System.out.println("in addYellow\n b:" + b + " r: " + r + " y: "
        // + y + " g: " + g);
    } else {
        return necklace;
    }
    ArrayList<Character> n1 = new ArrayList<Character>(necklace);
    ArrayList<Character> n2 = new ArrayList<Character>(necklace);
    n1 = addBlue(b, r, y, g, n1);
    n2 = addRed(b, r, y, g, n2);
    necklace = n1.size() > n2.size() ? n1 : n2;
    return necklace;
}

private ArrayList<Character> addGreen(Integer b, Integer r, Integer y, Integer g, ArrayList<Character> necklace) {
    char lastruby = necklace.size() > 0 && necklace.get(necklace.size() - 1) != null
            ? necklace.get(necklace.size() - 1) : 'z';
    if (anyRemaining(g) && (lastruby == 'r' || lastruby == 'g' || lastruby == 'z')) {
        necklace.add('g');
        g = g - 1;
        // System.out.println("in addGreen\n b:" + b + " r: " + r + " y: " +
        // y + " g: " + g);
    } else {
        return necklace;
    }
    ArrayList<Character> n1 = new ArrayList<Character>(necklace);
    ArrayList<Character> n2 = new ArrayList<Character>(necklace);
    n1 = addGreen(b, r, y, g, n1);
    n2 = addYellow(b, r, y, g, n2);
    necklace = n1.size() > n2.size() ? n1 : n2;
    return necklace;

}

private ArrayList<Character> addBlue(Integer b, Integer r, Integer y, Integer g, ArrayList<Character> necklace) {
    char lastruby = necklace.size() > 0 && necklace.get(necklace.size() - 1) != null
            ? necklace.get(necklace.size() - 1) : 'z';
    if (anyRemaining(b) && (lastruby == 'y' || lastruby == 'b' || lastruby == 'z')) {
        necklace.add('b');
        b = b - 1;
        // System.out.println("in addBlue\n b:" + b + " r: " + r + " y: " +
        // y + " g: " + g);
    } else {
        return necklace;
    }
    ArrayList<Character> n1 = new ArrayList<Character>(necklace);
    ArrayList<Character> n2 = new ArrayList<Character>(necklace);
    n1 = addBlue(b, r, y, g, n1);
    n2 = addRed(b, r, y, g, n2);
    necklace = n1.size() > n2.size() ? n1 : n2;
    return necklace;

}

private boolean anyRemaining(Integer b) {
    return b > 0;

}

}

这个解决方案可以做得更好吗?

1 个答案:

答案 0 :(得分:2)

TL; DR:您可以简单地将其计算为b + g + max(2 * min(r, y), 1 + 2 * min(r - 1, y))

你实现的问题是它像疯了一样分支:如果你有大量的珠子,它将采取每个选择 - 很多选择 - 所以它需要很长时间才能完成。

我认为最长项链的实际构造实际上非常简单(即使它会导致项链暗淡)。如果你想尝试一下,我已经实现了这个here

您可以构建所有可能转换的图表:

digraph G {
  "B" -> "B"
  "B" -> "R"
  "G" -> "G"
  "R" -> "G"
  "R" -> "Y"
  "G" -> "Y"
  "Y" -> "B"
  "Y" -> "R"
}

您只能访问这些节点中的每一个:您可以访问B节点b次,G节点g次等。

如果你每个珠子中至少有一个,你必须从B或R开始。所以,最长的项链是由:

(all B)+R+(all G)+Y+R+Y+R+...
  or
R+(all G)+Y+R+Y+R+...+(all B))

其中...表示重复Y / R交替,直到您的珠子用完为止。

所以长度是max(b + 2*min(r, y) + g, 1 + g + min(r-1, y) + b)

同样,如果某些数字为零,您可以考虑最佳路径。

如果你有一种零:

  • 如果b=0,请从R开始:最大长度为2*min(r, y + 1) + g
  • 如果r=0,请从B开始:最大长度为b
  • 如果g=0,请从B开始:最大长度为b + 2*min(r,y)
  • 如果y=0,请从B开始:最大长度为v + 1 + g

如果你有两种零:

  • 如果b=r=0,请从G开始:最大长度为g + 1
  • 如果b=g=0,请从R开始:最大长度为2*min(r, y + 1)
  • 如果b=y=0,请从R开始:最大长度为1 + g
  • 如果r=g=0,请从B开始:最大长度为b
  • 如果r=y=0,请从B开始:最大长度为b
  • 如果g=y=0,请从B开始:最大长度为b + 1

如果您有三种零(或者更确切地说,只有一种非零):

  • 如果b != 0,请从B开始:最大长度为b
  • 如果r != 0,请从R开始:最大长度为1
  • 如果g != 0,请从G开始:最大长度为g
  • 如果y != 0,请从Y开始:最大长度为1

你从来没有全部4种中的零,所以没有必要考虑那里。

因此,更有效的解决方案就是检查每一种情况。

但是,如果你比较这里的所有逻辑,你会发现有一个简单的表达式涵盖了所有的情况:

b + g + max(2 * min(r, y), 1 + 2 * min(r - 1, y));

所以,只需实现它!与原始代码不同,它可以立即有效运行。

这告诉你最长项链的长度;但要建造一条满足长度的项链并不难。