算法优化问题:N×N矩阵排列

时间:2016-01-26 00:56:38

标签: c++ algorithm matrix combinatorics

问题:确定n x n二进制矩阵的所有可能排列。

条件:每行和每列包含t 1;主对角线仅包含零;实际上不构造矩阵。

示例:n = 3,t = 2

0 1 1
1 0 1
1 1 0

我已经管理了一个递归解决方案,它迭代c ++中所有可能的排列。

我们的教授暗示,这种算法的优化在于实际上并没有迭代对角线左边的可能解决方案,但我无法得到它。

在此代码中,“状态向量”表示在相应列中尚未分配的数量,“puck”表示当前行和对角线索引。

#include <iostream>
#include <algorithm>
using namespace std;

// Global Variables
int n = 4;      // Length and height of matrix
int t = 1;  // Number of 1's in each row and column

int numSolutions(int state_vector[], int puck)
{
    int row[n];     // holds current row of matrix
    int total = 0;  // holds current number of permutations

    // Populate row with, n-t = 0, last t elements = 1
    // for n = 6, t = 2; (0, 0, 0, 0, 1, 1)
    // next_permutation() will be used to iterate over all permutations
    for(int i = 0; i < n; i++)
    {
        if(i < n-t)
            row[i] = 0;
        else
            row[i] = 1;
    }


    do
    {
        bool working = true;
        if(row[puck] == 0) // Test: is the diagonal element 0?
        {
            for (int i = 0; i < n; i++)
            {
                if( (state_vector[i] - row[i]) < 0) // Test: does the current row have positions available to hold a 1?
                {
                    working = false;
                }
            }
        }
        else
        {
            working = false;
        }

        // If the diagonal = 0, and there are positions able to hold a 1
        if(working)
        {
            int state_vector_copy[n];       //Holds copy of stat_vector

            // Copy state_vector
            for(int i = 0; i < n; i++)
            {
                state_vector_copy[i] = state_vector[i] - row[i];
            }

            if( puck == (n-1) )     // Test: On last row of martrix?
            {
                total++;            // Solution found, increment total
            }
            else
            {
                total += numSolutions(state_vector_copy, puck+1); // Recursive call to next row
            }
        }
    }while(next_permutation(row, row+n));

    return total;

}

// Pass off function
int numSolutions(int length)
{
    int state_vector[length];

    // Populate state_vector with values of t,   
    // In a n = 6 t = 2 example
    // (2, 2, 2, 2, 2, 2)
    for(int i = 0; i < length; i++)
    {
        state_vector[i] = t;
    }

    return numSolutions(state_vector, 0);
}

int main()
{

   cout << "Solution: " << numSolutions(n);
}

我的想法是,一旦我迭代了“冰球”右侧的所有位置,我只需要确定“冰球”左侧可用的位置并计算(位置选择t)以获得剩余的位置排列。

然而,我要么错了,要么没有实现它......或两者兼而有之。

非常感谢任何帮助。

0 个答案:

没有答案