【问题标题】:exercise with recursive backtracking递归回溯练习
【发布时间】:2014-12-29 22:52:04
【问题描述】:

我需要这个练习的帮助:
给出在输入中接收整数 n 并打印所有可能的矩阵 nxn 的伪代码,其中 a 的数量大于或等于 b 的数量,例如 n=2:(顺序不重要) 输出:
aa aa aa ab ab ba
咩咩咩咩咩咩咩咩
该算法的复杂度为 O($n^2*S(n)$)。其中 S(n) 是应打印的矩阵数。

现在我对回溯的技术算法不是很了解,因为我正在研究它......所以请如果有人可以帮助我进行练习和回溯......否则我永远不会通过这个考试。 谢谢你们;)

exercise(char[][] M,int i,int j,int[] arrRB,int[] arrCB, int n , int nelem )
{
    if(nelem == n*n)
    {
        for (int r=0 ; r<n ; r++)
        {
            for(int c=0 ; c<n ;c++)
                System.out.print(M[r][c]);
            System.out.print("\n");
        }
        System.out.print("\n");
    }
    else
    {

        if(i<n && j<n)
        {
            int r=i,c=j;
            if (arrRB[i] <= n-(i+1) && arrCB[j] <= n-(j+1))
            {
                M[i][j] = 'b';
                arrRB[i]++;
                arrCB[j]++;
                exercise(M,i,j+1,arrRB ,arrCB ,n,nelem+1); 
                exercise(M,i+1,j,arrRB ,arrCB ,n,nelem+1 ); 
                arrRB[r]--;
                arrCB[c]--;
            }
            M[r][c] = 'a';
            exercise(M,r+1,c,arrRB ,arrCB ,n, nelem+1);
            exercise(M,r,c+1,arrRB ,arrCB ,n,nelem+1 ); 
        }
    }
}
}

【问题讨论】:

  • 我想我必须在 M[i,j] 中放一个 'b',如果在行 'i' 和列 'j' 中,'b' 的数量是小于余数 (n-(i+1)) 和 (n-(j+1)) 。其中 n 是大小 i,j 索引。我使用两个数组来记住每行和每列的 b 的数量,因此例如 arrayBrow[i] 包含在行“i”中。但我的问题是使用递归管理索引。
  • 您实际上可以在每行内按行和列的顺序填充矩阵。类似于:将 a 或 b 放入 (i, j) 单元格,然后递归填充 (i, j + 1) 或 (i + 1, 0) 单元格(取决于 i 行是否结束)。
  • 对不起,我怎样才能在评论中插入代码?因为我想向你展示我的代码。
  • 为什么不将它添加到您的问题中?
  • 好的...我已经添加了它;)

标签: algorithm recursion recursive-backtracking


【解决方案1】:

看起来像这样(它是一个伪代码):

// Generates all matrices
void generate(char[][] matrix, int i, int j, int[] cntBRow, int[] cntBColumn) 
    if (i == n) // if the matrix is filled completely
        print(matrix) // just prints it
    else
        // Finds the next empty cell
        int nextI = i
        int nextJ = j + 1
        if (nextJ == n)
            nextI = i + 1
            nextJ = 0
        matrix[i][j] = 'a' // it is always possible to add 'a'
        generate(matrix, nextI, nextJ, cntBRow, cntBColumn)
        if ((cntBRow[i] + 1) * 2 <= matrix.length 
                && (cntBColumn[j] + 1) * 2 <= matrix.length) // if it is still possible to add 'b'
            cntBRow[i]++
            cntBColumn[j]++
            matrix[i][j] = 'b' // puts 'b' and continues generation
            generate(matrix, nextI, nextJ, cntBRow, cntBColumn)

 // Creates a new matrix and starts generation
 char[][] matrix = new char[n][n]
 generate(matrix, 0, 0, new int[n], new int[n])

这个想法是固定在递归填充矩阵时遍历单元格的顺序(在上面的代码中,单元格按一对(行号,列号)排序)。

【讨论】:

  • ahhh okok 我明白这个想法......只是,我不明白函数 canHaveEnoughA.... 为什么你要 2 * curB
  • @GabrieleSaturni 如果 b 的数量已经很大则停止生成(因此 b 的数量大于 a 的数量)。
  • 好的,首先非常感谢。所以我明白 canHaveEnoughA 的含义是什么......但我不明白为什么它应该工作,为什么你写 2*curB
  • 我误读了你的问题(问题本身说'a'的数量应该> ='b'的数量,但例子表明这应该适用于每行和每列)。
  • @GabrieleSaturni 我已经根据这个条件编辑了我的答案。