最简单的解决方案可能是探索所有可能性。
public static ArrayList<Integer> solve(int n,
ArrayList<Integer> moves, int bestMove,HashMap<Integer,Integer> memory) {
if (moves.size() >= bestMove) return null;
if (n == 1) return moves;
Integer sizeOfPathN= memory.get(n);
if (sizeOfPathN!=null && sizeOfPathN<=moves.size())return null;
memory.put(n,moves.size());
int size_1=Integer.MAX_VALUE, size_2 = Integer.MAX_VALUE, size_3 = Integer.MAX_VALUE;
ArrayList<Integer> moves3 = null, moves2 = null, moves1;
if (n % 3 == 0) {
ArrayList<Integer> c = new ArrayList<Integer>(moves);
c.add(3);
moves3 = solve(n / 3, c,bestMove,memory);
if (moves3!=null)
size_3 = moves3.size();
}
bestMove = Math.min(bestMove, size_3);
if (n % 2 == 0) {
ArrayList<Integer> c = new ArrayList<Integer>(moves);
c.add(2);
moves2 = solve(n / 2, c,bestMove,memory);
if (moves2!=null)
size_2 = moves2.size();
}
bestMove = Math.min(bestMove, size_2);
ArrayList<Integer> c = new ArrayList<Integer>(moves);
c.add(1);
moves1 = solve(n - 1, c,bestMove,memory);
if (moves1!=null)
size_1 = moves1.size();
int r = Math.min(Math.min(size_1, size_2),size_3);
if (r==size_1) return moves1;
if (r==size_2) return moves2;
return moves3;
}
解释:
n:n
moves : 一个包含动作的 ArrayList。 (用于打印浇注)
bestMove : 包含找到的最小解的大小的值。
memory : 一个 HashMap,包含之前探索的“状态”和路径的长度。
如果我们调用
公共静态 void main(String[] args) {
long a = System.currentTimeMillis();
Object[] sol=solve(10, new ArrayList<Integer>(),Integer.MAX_VALUE,new HashMap<Integer,Integer>()).toArray();
System.out.println(sol.length);
System.out.println(Arrays.toString(sol));
System.out.println((System.currentTimeMillis()-a));
}
输出将是:
3
[1, 3, 3]
1
相当于n-1, n/3,n/3(@Tristan 的最佳解决方案)
如果我们用1000 000 000 作为 n 来调用它:
30
[1, 3, 3, 3, 3, 1, 3, 3, 1, 3, 1, 1, 3, 3, 3, 3, 1, 2, 2, 1, 3, 2, 1, 3, 3, 2, 1, 3, 2, 2]
55
如果我们用11 调用它:
4
[1, 1, 3, 3]
1
编辑:
如果只需要移动次数:
public static int solve(int n,int moves,int bestMove,HashMap<Integer,Integer> memory) {
if (moves >= bestMove) return Integer.MAX_VALUE;
if (n == 1) return moves;
Integer sizeOfPathN= memory.get(n);
if (sizeOfPathN!=null && sizeOfPathN<=moves)return Integer.MAX_VALUE;
memory.put(n,moves);
int size_1=Integer.MAX_VALUE;
int size_2 = Integer.MAX_VALUE;
int size_3 = Integer.MAX_VALUE;
moves=moves+1;
if (n % 3 == 0) size_3 = solve(n / 3, moves,bestMove,memory);
bestMove = Math.min(bestMove, size_3);
if (n % 2 == 0) size_2=solve(n >> 1, moves,bestMove,memory);
bestMove = Math.min(bestMove, size_2);
size_1 = solve(n - 1, moves,bestMove,memory);
return Math.min(Math.min(size_1, size_2),size_3);
}
调用这个方法
long a = System.currentTimeMillis();
System.out.println(
solve(1000 *1000*1000, 0,Integer.MAX_VALUE,new HashMap<Integer,Integer>()));
System.out.println((System.currentTimeMillis()-a));
输出:
30
24
够快