Java - 多少个数字组合

时间:2012-04-26 14:39:07

标签: java numbers combinations

任何人都可以告诉我如何在Java中计算以下问题。有多少可能的有效数字,其中有效数字是0-9之间的任何数字,10位数字的长度,不包括#或*,一张国际象棋可以在通过电话键盘旅行时追踪。这里说我有一个国王,它只能在真实游戏中向任何方向移动,但一次只能移动一个单元格。

所以小键盘看起来像这样:

         1  2  3
         4  5  6
         7  8  9
         *  0  #

因此每件作品会进行10次移动,并且由它创建的每个唯一编号都是有效数字。一件作品从最初的起始位置开始。

更新: 一块可以移动或停留在一个地方(移动或停留都将算作移动)以及重新访问单元格(只要它在各自的移动权限内允许)。因此,例如,如果King从位置1移动,则创建有效数字编号的三个有效10移动路径可以是1236547890或1111111111或1212121212

这是一个小版本的四个细胞方垫的代码,只有4个单元只是为了测试目的:

public class King
{
private static final Integer[] ALLOWED_FROM_1 = {2, 3, 4};
private static final Integer[] ALLOWED_FROM_2 = {1, 3, 4};
private static final Integer[] ALLOWED_FROM_3 = {1, 2, 4};
private static final Integer[] ALLOWED_FROM_4 = {1, 2, 3};
List<Integer> visited;

public King()
{
    this.visited = new ArrayList<Integer>();

}

public List<Integer> get_destinations(int currentPos, int noOfMoves)
{
    if (noOfMoves == 0)
    {
        visited.add(currentPos);
        return visited;

    }
    else
    {

        List<Integer> possibleMoves = getPossibleMoves(currentPos);

        for (int i = 0; i < possibleMoves.size(); i++)
        {
            visited.add(possibleMoves.get(i));
            get_destinations(possibleMoves.get(i), noOfMoves - 1);

        }

        return visited;
    }



}


private List<Integer> getPossibleMoves(int currentPos)
{

    List<Integer> possibleMoves = new ArrayList<Integer>();

    switch (currentPos)
    {
        case 1 : possibleMoves.addAll(Arrays.asList(ALLOWED_FROM_1));
            break;

        case 2: possibleMoves.addAll(Arrays.asList(ALLOWED_FROM_2));
            break;

        case 3 : possibleMoves.addAll(Arrays.asList(ALLOWED_FROM_3));
            break;

        case 4 : possibleMoves.addAll(Arrays.asList(ALLOWED_FROM_4));
    }

    return possibleMoves;

}
}

上面的代码只产生部分答案,缺少许多不同的排列。主要问题是如何确保它能够确保它产生所有排列以及在上面的代码中精确到达的那一刻我是否达到应存储并随后检索的4位数(4次移动后)。另外,我如何避免重新访问相同的序列,例如1234 1234,所以基本上优化它,这样它就不会产生相同的路径序列/有效数字。

非常感谢。

3 个答案:

答案 0 :(得分:0)

这是一些可能有用的伪代码。您可以通过以下方式递归地解决问题:

// Returns a list of all the destinations given a current location
// and the number of moves allowed (10 for King)
list<int> get_destinations(int cur_location, int num_moves) {
  // Base case. If no more moves are allowed, return current location as list.
  if(num_moves == 0) {
    return as_list(cur_location);
  } else {
    // List of all destinations possible from here
    list<int> destinations;
    // Get all the possible moves that are 1 step away.
    // For example: from 1, we would return 2 and 4
    list<int> possible_moves = get_possible_moves(cur_location);

    // For each of the moves generated from the last step,
    // recursively call get_destinations() with (num_moves - 1)
    for(int n:possible_moves) {
      destinations += get_destinations(n, num_moves - 1);
    }

    return destinations;
  }
}

然后您将使用以下内容调用此函数:

get_unique_nums(get_destinations); // Returns the set in the form you need it

祝你的作业好运!

答案 1 :(得分:0)

似乎很琐碎的学术递归问题。只要允许递归,语言就无关紧要了。

你需要:

  1. 设置 一个。 F(n,m)数组(在您的情况下值为3x4) 湾和作品的初始位置。 C。允许你可能想要定义委托(函数指针,匿名类)函数的任意部分来定义允许的移动

  2. 创建一个递归可调用函数,用于标识下一个作为输入的符合条件的位置: 一个。当前件位(i,j), 湾第一次迭代中的递归深度

  3. 从depth = 10

  4. 上的递归函数返回
  5. 如果你还需要所有的序列,让这个递归函数可以返回(非void类型)我会说字符串是最好的

  6. 如果你想让代码更简单,你不需要在允许的单元格集的每一步上验证*,#的存在,只需验证最终的10个符号长字符串,以便可解析为UNSIGNED LONG。虽然它使递归时间过长。

答案 2 :(得分:0)

对于国王来说,这种重复即将来临。 2,1,2,1, 3,4,3,1 ,2,3,4,2, 3,4,3,1

您可以使getPossibleMove()函数以特定顺序返回单元格。 这有助于避免重复路径。仅按数字顺序说,它应该返回

2,1,2,1,
2,1,3,3,
2,1,2,5,
2,1,4,1,
2,1,4,5,
2,1,4,7

此外,如果您不想让该块移动到同一个单元格,只需删除getPossibleMove()函数中的那些单元格。

我没有得到要写的代码,所以只写了理论解释。