Algorithm 与向量吻合
假设给定一个向量v[1..d^2],其中包含d^2个元素 v[1]v[2]v[3]v[4]v[5]。。。v[d^2] 我们希望对角填充dxd矩阵M,而不是逐行或逐列填充 例如,如果d=4,则生成的矩阵为 v[01]v[03]v[06]v[10] v[02]v[05]v[09]v[13] v[04]v[08]v[12]v[15] v[07]v[11]v[14]v[16] 这种技术记住了吻合,但在这种情况下,我们希望完全填充平方矩阵Algorithm 与向量吻合,algorithm,matrix,Algorithm,Matrix,假设给定一个向量v[1..d^2],其中包含d^2个元素 v[1]v[2]v[3]v[4]v[5]。。。v[d^2] 我们希望对角填充dxd矩阵M,而不是逐行或逐列填充 例如,如果d=4,则生成的矩阵为 v[01]v[03]v[06]v[10] v[02]v[05]v[09]v[13] v[04]v[08]v[12]v[15] v[07]v[11]v[14]v[16] 这种技术记住了吻合,但在这种情况下,我们希望完全填充平方矩阵 如何设计一个算法,在给定向量v和维数d的情况下,它能回答上述矩阵?
如何设计一个算法,在给定向量v和维数d的情况下,它能回答上述矩阵?我研究了这个问题,我认为我找到了一种模式,可以将矩阵中的坐标映射到向量中的索引。查看4x4示例中用于填充矩阵的索引之间的差异:
0 (+2) 2 (+3) 5 (+4) 9
(+1)
1 (+3) 4 (+4) 8 (+4) 12
(+2)
3 (+4) 7 (+4) 11 (+3) 14
(+3)
6 (+4) 10 (+3) 13 (+2) 15
列开头的偏移量以算术级数增加,元素之间的偏移量可以从列表中看到:offsets=[2,3,4,4,3,2]
offset by The current row and column。i、 e.要从(r,c)
转到(r,c+1)
您需要添加偏移量[r+c]
我们可以将此偏移定义为一个函数:
inline int
offset(int d, int i)
{
return i+2 - std::max(0, 2*(i-d+2)-1);
}
它生成如下序列:
d=4: 2, 3, 4, 4, 3, 2
d=5: 2, 3, 4, 5, 5, 4, 3, 2
现在,我们可以在循环中使用它来查找用于填充矩阵的索引:
for( int rOff = 0, r = 0
; r < d
; rOff += ++r
)
for( int i = rOff, c = 0
; c < d
; i += offset(d, r + c++)
)
matrix[r][c] = v[i];
作为健全性检查,这里是上述循环的输出,但是用
std::cout替换matrix[r][c]=v[i]
时,如果您只考虑两个循环,事情就相当简单:一个循环遍历上部反三角形,另一个循环遍历下部反三角形。对于第一个循环,向下推进外循环中的行,内循环向上和向右移动。在第二种情况下,在外环中穿过立柱,在内环中再次向上向右移动。下面是一个完整的C程序:
#include <stdio.h>
int main(void)
{
int d = 4, v[d * d], m[d][d], start, i, j, k, i0, j0;
// Fill v with 1,2,...d^2
for (int i = 0; i < d * d; i++) v[i] = i+1;
// Start dovetail.
k = 0;
for (i0 = 0; i0 < d; i0++) // Down left column
for (i = i0, j = 0; i >= 0; i--, j++)
m[i][j] = v[k++];
for (j0 = 1; j0 < d; j0++) // Across bottom row
for (i = d - 1, j = j0; j < d; i--, j++)
m[i][j] = v[k++];
// End dovetail.
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) printf("%4d", m[i][j]);
printf("\n");
}
return 0;
}
#include <stdio.h>
int main(void)
{
int d = 4, v[d * d], m[d][d], start, i, j, k, i0, j0;
// Fill v with 1,2,...d^2
for (int i = 0; i < d * d; i++) v[i] = i+1;
// Start dovetail.
k = 0;
for (i0 = 0; i0 < d; i0++) // Down left column
for (i = i0, j = 0; i >= 0; i--, j++)
m[i][j] = v[k++];
for (j0 = 1; j0 < d; j0++) // Across bottom row
for (i = d - 1, j = j0; j < d; i--, j++)
m[i][j] = v[k++];
// End dovetail.
// Print the result.
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) printf("%4d", m[i][j]);
printf("\n");
}
return 0;
}
#包括
内部主(空)
{
int d=4,v[d*d],m[d][d],开始,i,j,k,i0,j0;
//用1,2,…d^2填充v
对于(inti=0;i=0;i--,j++)
m[i][j]=v[k++];
对于(j0=1;j0
如果您只考虑两个循环嵌套,事情就相当简单:一个用于遍历上部反三角形,另一个用于下部反三角形。使用此功能,您只需要简单的计数器,不需要执行max
或min
操作
对于第一个循环,在外部循环中向下推进左列的行,内部循环向上和向右移动
在第二个循环中,在外部循环中穿过底部行的列,然后再次与内部循环一起向上和向右移动。下面是一个C程序:
#include <stdio.h>
int main(void)
{
int d = 4, v[d * d], m[d][d], start, i, j, k, i0, j0;
// Fill v with 1,2,...d^2
for (int i = 0; i < d * d; i++) v[i] = i+1;
// Start dovetail.
k = 0;
for (i0 = 0; i0 < d; i0++) // Down left column
for (i = i0, j = 0; i >= 0; i--, j++)
m[i][j] = v[k++];
for (j0 = 1; j0 < d; j0++) // Across bottom row
for (i = d - 1, j = j0; j < d; i--, j++)
m[i][j] = v[k++];
// End dovetail.
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) printf("%4d", m[i][j]);
printf("\n");
}
return 0;
}
#include <stdio.h>
int main(void)
{
int d = 4, v[d * d], m[d][d], start, i, j, k, i0, j0;
// Fill v with 1,2,...d^2
for (int i = 0; i < d * d; i++) v[i] = i+1;
// Start dovetail.
k = 0;
for (i0 = 0; i0 < d; i0++) // Down left column
for (i = i0, j = 0; i >= 0; i--, j++)
m[i][j] = v[k++];
for (j0 = 1; j0 < d; j0++) // Across bottom row
for (i = d - 1, j = j0; j < d; i--, j++)
m[i][j] = v[k++];
// End dovetail.
// Print the result.
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) printf("%4d", m[i][j]);
printf("\n");
}
return 0;
}
请注意,每次迭代,放置向量元素的索引都会被交换。此外,坐标的最高维度与下面的维度交替使用,因此它们的总和总是相同的:例如:对于v4 v5 v6
:(3,1)(2,2)(1,3)
:因此,在这种情况下,所有坐标的总和都是4。这和最后一个都是非常好的简单解决方案,我喜欢它。我不能选择一个答案来支持另一个,因为有不止一个解决方案,但我正在投票。嗯。。。谢谢我不知道为什么创建了两个不同的帖子(一个bug!)。我刚把原稿编辑了一点,很好。我也在想类似的事情,我发现矩阵[r][c]=(I+I^2+2ij+j(j+3))/2
对于高于上二次/反对角线的值,但我没有找到另一部分的闭合形式。这是一个很好的答案,我不能选择一个答案来支持另一个,因为提出的解决方案不止一个,但我正在投票支持它。
#include <stdio.h>
int main(void)
{
int d = 4, v[d * d], m[d][d], start, i, j, k, i0, j0;
// Fill v with 1,2,...d^2
for (int i = 0; i < d * d; i++) v[i] = i+1;
// Start dovetail.
k = 0;
for (i0 = 0; i0 < d; i0++) // Down left column
for (i = i0, j = 0; i >= 0; i--, j++)
m[i][j] = v[k++];
for (j0 = 1; j0 < d; j0++) // Across bottom row
for (i = d - 1, j = j0; j < d; i--, j++)
m[i][j] = v[k++];
// End dovetail.
// Print the result.
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) printf("%4d", m[i][j]);
printf("\n");
}
return 0;
}
1 3 6 10
2 5 9 13
4 8 12 15
7 11 14 16