0

我不确定我是否习惯于更正标题中的措辞来描述问题。请随意编辑它以反映下面的描述。

假设我有一个数独求解程序,假设输入矩阵如下,

A = randi(10,[9,9])-1;

我从 1 到 9 逐列索引 3x3 子矩阵。假设表示该索引的变量nSubMat可以采用 1 到 9 之间的任何值。

我按以下方式索引子矩阵,

SubMat(nSubMat) = A((1:3)+(3*floor((nSubMat-1)/3)),(1:3)+(3*mod(nSubMat-1,3)));

现在,我想访问和修改 SubMat 的 (2x3) 位置中的值,而不必首先创建 SubMat(比如避免不必要的副本)。

详细地说,如果我有一个函数 submatrix() 可以实现上述内容,我的语句将如下所示,

submatrix(A((1:3)+(3*floor((nSubMat-1)/3)),(1:3)+(3*mod(nSubMat-1,3))),[2,3]) = 5;

甚至,

submatrix(A((1:3)+(3*floor((nSubMat-1)/3)),(1:3)+(3*mod(nSubMat-1,3))),[2:3,2:3]) = [1 2;3 4];

我知道 Matlab 解释器会自动优化 LHS=RHS 类型分配以提高速度,但上述矩阵运算很重要,原因(算法上)不仅仅是减少副本和加速代码,我不会在这里详述。我在一个名为 Armadillo 的 C++ 库中看到了所需的语法,但我不确定 MATLAB 是否也能做到这一点。

4

2 回答 2

1

您可以使用简单的线性索引来做到这一点。以下代码是不言自明的。

matrixRows=9;
matrixCols=9;
blockRows=3;
blockCols=3;
accessRow=2;
accessCol=3;

A = randi(10,[matrixRows,matrixCols])-1;
allPos=allcomb(accessRow:blockRows:matrixRows,accessCol:blockCols:matrixCols);
linPos=sub2ind(size(A),allPos(:,1),allPos(:,2));

% access them as usual and put any value
A(linPos)=-100;

结果:

A =

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

运行以上代码后:

A =

 8     9     7     3     6     4     1     6     8
 9     1  -100     6     3  -100     4     8  -100
 1     9     6     1     9     6     9     9     9
 9     9     0     7     0     7     3     5     3
 6     4  -100     0     4  -100     5     1  -100
 0     8     9     2     3     2     2     1     2
 2     1     6     0     7     6     7     2     6
 5     4  -100     0     7  -100     2     8  -100
 9     9     7     8     1     1     5     2     3

注意:allcomb生成输入参数的所有可能组合。您也可以使用这个allcomb(根据答案)更快的方法。

于 2015-05-31T03:57:35.497 回答
1

这是任何大小的数独游戏的通用功能。

function index = SudukoIndex(varargin)
%%%SudukoIndex provides the index or indicies of a sub-block of any n*n
%%%Suduko puzzle

%Possible inputs
%   One (1) number (i) between 1 and n will provide a sqrt(n) * sqrt(n) set of
%      indicies from the i-th block. Note this is counted using Matlab
%      syntax going from top to bottom then left to right, a simple check
%      for this can be found by typing the command 'reshape(1:n, sqrt(n),
%      sqrt(n))' into the command window.
%   Two (2) numbers between 1 and n will provide the single number index of
%       the row, column combination
%   Three (3) numbers the first (i) between 1 and n and the second (j) and 
%       third (k) between 1 and sqrt(n) will provide the index of the (j,k)
%       point in the i-th cell
n = 9;

if nargin == 1
    sM = varargin{1};
    majorColumn = floor((sM-1)/sqrt(n)) + 1;
    majorRow = mod(sM-1, sqrt(n)) + 1;

    x = (1:sqrt(n))';
    y = (1:n:n^1.5);
    [x, y] = meshgrid(x, y);
    m = (x + y - 1)';

    index = (n^1.5)*(majorColumn - 1) + sqrt(n)*(majorRow - 1) + m;
elseif nargin == 2
    index = n*(varargin{2} - 1) + varargin{1};
elseif nargin == 3
    m = nsm(varargin{1});
    index = m(varargin{2}, varargin{3});
end
end
于 2015-05-31T04:57:33.353 回答