Java 最快的硬币运动
我有一个难题,我需要通过在某些条件下删除17个,将一个数字减为零。下面是让你理解的谜题 从138枚硬币开始,找到最少的移动次数,精确到0枚硬币。每次移动你可以(a)弃掉17枚硬币,(b)弃掉1枚硬币或(c)弃掉一半硬币(但前提是你目前拥有偶数枚硬币)。编写一个程序,测试所有可能的移动组合,并打印最快移动组合所需的移动数 我用下面的代码找到了最快的移动。现在,我需要找出其他可能的动作,但我被卡住了。有人能帮忙吗Java 最快的硬币运动,java,puzzle,Java,Puzzle,我有一个难题,我需要通过在某些条件下删除17个,将一个数字减为零。下面是让你理解的谜题 从138枚硬币开始,找到最少的移动次数,精确到0枚硬币。每次移动你可以(a)弃掉17枚硬币,(b)弃掉1枚硬币或(c)弃掉一半硬币(但前提是你目前拥有偶数枚硬币)。编写一个程序,测试所有可能的移动组合,并打印最快移动组合所需的移动数 我用下面的代码找到了最快的移动。现在,我需要找出其他可能的动作,但我被卡住了。有人能帮忙吗 package com.infy.cis.test; public class Co
package com.infy.cis.test;
public class CoinMovementPuzzle {
static int times=0;
public static void main(String[] args) {
// TODO Auto-generated method stub
numDiv(138,2,17,1);
}
public static void numDiv(int a, int b,int c,int d) {
if(a!=0)
{
int remainder=a%b;;
if(remainder==0 && a>=2)
{
evenNumber(a,b);
}
else if(remainder!=0 && a>=17)
{
oddNumber17(a,c);
}
else
{
oddNumber1(a,d);
}
}
System.out.println("FINAL"+times);
}
private static void oddNumber1(int a,int d) {
// TODO Auto-generated method stub
a=a-d;
times=times+1;
System.out.println("odd number::"+a+"::"+times);
numDiv(a, 2,17,1);
}
private static void oddNumber17(int a,int c) {
// TODO Auto-generated method stub
//int rem;
int rem=a%c;
a/=c;
times=times+a;
System.out.println("odd number::"+a+"::"+times);
numDiv(rem, 2,17,1);
}
private static void evenNumber(int a,int b) {
// TODO Auto-generated method stub
a/=2;
times=times+1;
//System.out.println(a/=b);
//remainder=a%b;
System.out.println("Value of a"+a);
System.out.println("even number::"+a+"::"+times);
numDiv(a, 2,17,1);
}
}
此解决方案将按相反顺序打印出最佳(但不是全部)移动: 它的工作原理是使用广度优先搜索算法,尝试所有可能的组合,并在每个阶段选择最佳组合
import java.util.ArrayList;
import java.util.List;
public class Main {
List<String> getMinMoves(int amount){
if (amount <= 0){
return new ArrayList<String>();
}
int numMovesSubtractingSeventeen = Integer.MAX_VALUE;
List<String> movesSubtractingSeventeen = null;
if (amount >= 17){
movesSubtractingSeventeen = getMinMoves(amount - 17);
numMovesSubtractingSeventeen = 1 + movesSubtractingSeventeen.size();
}
List<String> movesSubtractingOne = getMinMoves(amount - 1);
int numMovesSubtractingOne = 1 + movesSubtractingOne.size();
List<String> movesDividingByTwo = null;
int numMovesDivideByTwo = Integer.MAX_VALUE;
if (amount % 2 == 0) {
movesDividingByTwo = getMinMoves(amount/2);
numMovesDivideByTwo = 1 + movesDividingByTwo.size();
}
if (numMovesSubtractingSeventeen < numMovesSubtractingOne){
if (numMovesSubtractingSeventeen < numMovesDivideByTwo){
movesSubtractingSeventeen.add("Subtract 17 from " + amount);
return movesSubtractingSeventeen;
} else {
movesDividingByTwo.add("Divide " + amount + " by 2");
return movesDividingByTwo;
}
} else {
if (numMovesSubtractingOne < numMovesDivideByTwo) {
movesSubtractingOne.add("Subtract 1 from " + amount);
return movesSubtractingOne;
}
else {
movesDividingByTwo.add("Divide " + amount + " by 2");
return movesDividingByTwo;
}
}
}
public static void main(String[] args) {
Main main = new Main();
List<String> moves = main.getMinMoves(138);
System.out.println("Min number of moves: " + moves.size());
for (String move : moves){
System.out.println(move);
}
}
}
import java.util.ArrayList;
导入java.util.List;
公共班机{
列表getMinMoves(整数金额){
如果(金额=17){
movessubtractingseven=getMinMoves(金额-17);
nummovesSubscriptingsEventeen=1+MovesSubtracting 17.size();
}
List movessubtratingone=getMinMoves(金额-1);
int nummovessublatingone=1+movessubtratingone.size();
List movesDividingByTwo=null;
int numMovesDivideByTwo=整数.MAX_值;
如果(金额%2==0){
movesDividingByTwo=getMinMoves(金额/2);
nummovesdividbytwo=1+movesDividingByTwo.size();
}
if(nummovessublatingeventien
如果有多个解决方案是最优的,您可以修改代码以返回一组列表。这类似于更改问题。如果您想找到移动次数最少的方法,那么动态规划方法就可以了。您可以设置一个数组
a[i]
,i=0..138
,并从最小到最大进行构建。从a[0]=0开始。存储在a[i]
中的数字是min(a[i-1]+1,a[i-17]+1,a[i/2]+1(如果我是偶数))
。努力达到a[138]
。然后要找到实际的移动顺序,找出a[138-1]
,a[138-17]
,a[138/2]
中哪一个小于a[138]
,然后重复,直到你点击0
a[0] = 0
for i = 1 to 138
if (i<17)
if (i odd)
a[i] = a[i-1]+1
else // i even
a[i] = min(a[i-1]+1, a[i/2]+1)
else // i >= 17
if (i odd)
a[i] = min(a[i-1]+1, a[i-17]+1)
else // i even
a[i] = min(a[i-1]+1, a[i-17]+1, a[i/2]+1)
// end if
// a[138] now contains the minimum number of moves
// find the actual sequence by working backwards
i = 138
while (i>0)
if a[i-1] < a[i]
print -1
i = i-1
else if a[i-17] < a[i]
print -17
i = i-17
else if a[i/2] < a[i]
print /2
i = i/2
else
// shouldn't end up here
print error
您的初始呼叫应该是sequenceOfMoves(“,138)
要回答这个问题,您需要存储序列而不是打印序列,然后在递归完成后,在存储中搜索最短的移动序列。打印所有内容,将最短者标记为优胜者。首先格式化代码,然后请告诉我们您的具体位置和尝试。我认为您需要的是。创建一棵树,其中第一步是一半、17和1。这将创建3个节点。对于每个节点,使用合法移动创建新节点。当您创建了所有节点(换句话说,当您的所有子节点都为零)后,您就创建了包含所有移动组合的树。您确定您的算法找到了最快的移动吗?我看到,运行代码可以得到6个移动的结果,这是最快的路径。但是接下来的一系列动作。从138开始,除以2(69),减去1(68),除以2(34),除以2或减去17(17),减去17(0)。只有5步。我投票结束这个问题作为离题,因为这是关于解决一个数学问题,而不是编程。嗨,爱德华,能不能请你对数组部分进行重新校准。我想不起来。也许一小段代码会有所帮助。谢谢..我画了算法。谢谢爱德华:)。这帮了大忙!
sequenceOfMoves(string sequenceSoFar, int targetNumber)
if targetNumber is 0, print sequenceSoFar // done
if targetNumber > 0 sequenceOfMoves(sequenceSoFar + "-1", targetNumber-1)
if targetNumber > 16 sequenceOfMoves(sequenceSoFar + "-17", targetNumber-17)
if targetNumber is even sequenceOfMoves(sequenceSoFar + "/2", targetNumber/2)