问题:确定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)以获得剩余的位置排列。
然而,我要么错了,要么没有实现它......或两者兼而有之。
非常感谢任何帮助。