Java最短路径为1

时间:2017-10-17 00:21:19

标签: java

旧程序

public class JavaApplication7 {
    public static void main(String[] args) {
        String n = ""; // any given whole positive integer
        long solution = 0;
        double t = Double.parseDouble(n);
        double pow = nearpow(t);
        double nearpow = Math.pow(2, nearpow(t));
        double difference = Math.abs(t-nearpow);
        while(t!=1){
            if(t==nearpow){
                solution+=pow;
                t/=nearpow;
            }
            if(nearpow<t&&t!=1){
                t = t - difference;                 
                solution+=difference;
                t = t / nearpow;
                solution+=pow;                
            }
            else if(nearpow>t&&t!=1){
                t+=difference;                
                solution+=difference;      
                t/=nearpow;
                solution+=pow;
                }
            }
        System.out.println(solution);
    } 
    public static double nearpow(double t){
        double log = Math.log(t) / Math.log(2);

        long roundLog = Math.round(log);
        double dec = Math.abs(log-roundLog);
        long lowPow = (long)(log-dec);
        long highPow = lowPow+1;
        if(Math.abs(t-Math.pow(2,highPow))<Math.abs(t-Math.pow(2,lowPow))){
            return highPow;
        }
        else{
            return lowPow;
        }
    }
}

编程以找到操作数最少的操作,使用+1 -1和/ 2的有限操作使数字降至1,该测试适用于我使用过的情况(4 ,5,15,30,35,60值,但它不能以更高的值运行。任何人都可以看到更高值的失败点,例如726给出259次操作得到1。

新计划

    String n = "54123";
    BigInteger t = new BigInteger(n);
    BigInteger one = new BigInteger("1");
    System.out.println(t);
    int solution =0;       
    while(!t.equals(one)){
        if(((t.and(one)).equals(BigInteger.ZERO))){
            System.out.println(t+"/2 =");
            t=t.shiftRight(1);
            solution++;  
            }
        else if((t.and(one)).equals(BigInteger.ONE)&&(((t.shiftRight(1).and(one))).equals(BigInteger.ONE))&&(((t.shiftRight(2).and(one))).equals(BigInteger.ONE))){
            System.out.println(t+"+2 =");
            t=t.add(one);
            solution++;

        }
        else if(t.and(one).shiftRight(1).equals(BigInteger.ZERO)&&t.and(one).equals(one)){
            System.out.println(t+"-1 =");
            t=t.subtract(one);            
            solution++;
        }
    }
    System.out.print(solution);

我对按位操作很新,所以我需要一些帮助来找到问题的新错误,因为我写的内容对我来说仍然是一个新东西并且添加到按位操作的新用法我必须写入BigInteger哪个术语对我来说很难理解,但是我使用它的术语应该可以工作,但我找不到为什么它不会的原因,之前使用的例子是762给出的它提供了259次操作和新程序15,由于条款的新颖性,我仍然无法识别故障。 我写的解决方案(工作)

    String n = "762";
    BigInteger t = new BigInteger(n);
    BigInteger three = new BigInteger("3");
    BigInteger one = new BigInteger("1");
    System.out.println(t);
    int solution =0;       
    while(!t.equals(one)){
        if(t.equals(three)){
            t=t.subtract(one);
            solution++;
        }
        if(((t.and(one)).equals(BigInteger.ZERO))){
            t=t.shiftRight(1);
            solution++;  
            }
        else if((t.and(one)).equals(BigInteger.ONE)&&
(((t.shiftRight(1).and(one))).equals(BigInteger.ONE))){
            t=t.add(one);
            solution++;

        }
        else 
if(t.and(one).shiftRight(1).equals(BigInteger.ZERO)&&t.and(one).equals(one)){
            t=t.subtract(one);            
            solution++;
        }
    }
    System.out.print(solution);
}

}

3 个答案:

答案 0 :(得分:4)

这是一个位操作的问题,正如除以2规则所示。

让我们看一下评论(现已删除)中提到的数字762(基数10),又名1011111010(基数2)。

除以2表示将位移到右侧。大概你不允许这样做,除非数字可以被2整除,即最右边的位是0。

所以,如果我们能够向右转,我们就会这样做。如果没有,我们可以减去一个以清除该位。

然而,如果下一位也是1,我们可以改为加1,因此在一次操作中将多个1位翻转为0,例如, 100111 + 1 = 101000

作为特殊考虑因素,11不应添加1,因为这会11100101,即3次操作。相反,您会减去1以获得11101

          1011111010
 1:  /2 =  101111101
 2:  -1 =  101111100
 3:  /2 =   10111110
 4:  /2 =    1011111
 5:  +1 =    1100000
 6:  /2 =     110000
 7:  /2 =      11000
 8:  /2 =       1100
 9:  /2 =        110
10:  /2 =         11
11:  -1 =         10
12:  /2 =          1

12 操作中的解决方案。

现在你只需要为它编写代码。

答案 1 :(得分:1)

表达式

        (!((t.and(one)).shiftRight(1)).equals(BigInteger.ZERO))

        (!((t.and(one)).shiftRight(2)).equals(BigInteger.ZERO))

错了。它们用于测试非{0}的t的第二和第三最低有效位,但它们不是。他们每次只返回false

这两个表达式都以t.and(one)开头,它隔离了t last 位,而不是倒数第二位或倒数第三位。然后每个都移开那一点,有效地离开BigInteger.ZERO。因此,这两个测试都归结为BigInteger.ZERO.equals(BigInteger.ZERO),并且由于BigInteger.ZERO永远不会 等于BigInteger.ZERO,因此无论false是什么{t {1}}是。

你想要的是

        (!((t.shiftRight(1)).and(one)).equals(BigInteger.ZERO))

        (!((t.shiftRight(2)).and(one)).equals(BigInteger.ZERO))

首先执行移位,将t的所需位移到新BigInteger的最后位置,然后.and(one)将其隔离以进行测试。现在,您实际上正在测试t的倒数第二位和倒数第三位。

答案 2 :(得分:0)

我写了@Andreas按位方法的版本。

public static enum Op
{
    PLUS_1, MINUS_1, DIV_2
}
public static void shortest( final long value, final List<Op> steps )
{
    System.out.println( Long.toBinaryString( value ) );
    if ( value > 1L )
    {
        if ( ( value & 1L ) == 0L )
        {
            // last bit is 0
            steps.add( Op.DIV_2 );
            shortest( value / 2L, steps );
        }
        else if ( Long.highestOneBit( value ) == Long.bitCount( value ) )
        {
            // only 1 bits
            steps.add( Op.MINUS_1 );
            shortest( value - 1L, steps );
        }
        else if ( ( value & 3L ) == 3L )
        {
            // last bits are 11
            steps.add( Op.PLUS_1 );
            shortest( value + 1L, steps );
        }
        else
        {
            // last bits are 01
            steps.add( Op.MINUS_1 );
            shortest( value - 1L, steps );
        }
    }
}
public static void print( final long value, final List<Op> steps )
{
    System.out.printf( "%d = %<x = %s = %d %s\n", value, Long.toBinaryString( value ),
                       steps.size(), steps );
}
public static void main( final String[] args )
{
    final List<Op> steps = new ArrayList<>();
    shortest( 726, steps );
    print( 726, steps );

    steps.clear();
    shortest( 762, steps );
    print( 762, steps );
}

输出:

1011010110
101101011
101101100
10110110
1011011
1011100
101110
10111
11000
1100
110
11
10
1
726 = 2d6 = 1011010110 = 13 [DIV_2, PLUS_1, DIV_2, DIV_2, PLUS_1, DIV_2, DIV_2, PLUS_1, DIV_2, DIV_2, DIV_2, MINUS_1, DIV_2]
1011111010
101111101
101111100
10111110
1011111
1100000
110000
11000
1100
110
11
10
1
762 = 2fa = 1011111010 = 12 [DIV_2, MINUS_1, DIV_2, DIV_2, PLUS_1, DIV_2, DIV_2, DIV_2, DIV_2, DIV_2, MINUS_1, DIV_2]