我正在尝试编写代码来检测矩阵是否是Hankel矩阵的排列,但我不能想到除了非常慢的暴力之外的有效解决方案。这是规范。
输入: n个n矩阵M,其条目为1或0。
输入格式:空格分隔的行。每行一行。例如
0 1 1 1
0 1 0 1
0 1 0 0
1 0 1 1
输出:M的行和列的排列,如果可能,则M为Hankel matrix。 Hankel矩阵具有恒定的倾斜对角线(正倾斜对角线)。
当我说排列时,我的意思是我们可以将一个排列应用于行的顺序,并将一个可能不同的排列应用于列。
我会非常感谢任何想法。
答案 0 :(得分:2)
不失一般性,我们假设0比1更少。然后我们可以在Hankel矩阵中找到可能的对角线,它可以是0,以便在整个矩阵中给出适当数量的0。而且,这将为我们提供可能的Hankel矩阵。从那里,您可以计算每列中的0的数量,并将其与原始矩阵的列中的0的数量进行比较。完成此操作后,您可以在更小的空间内执行强力搜索:在具有正确数字0的列和行上进行置换。
示例: OP建议使用7 x 4的4x4矩阵。我们需要使用集合{4,3,3,2,2,1,1}
对其进行分区。所以,或分区将是:
{4,3}
{4,2,1}
(其中2个矩阵){3,3,1}
{3,2,2}
{3,2,1,1}
(其中2个矩阵)这给了我们Hankel矩阵(不包括对称性)
1 1 0 0 1 1 1 0 0 1 1 0 1 1 0 1
1 0 0 1 1 1 0 1 1 1 0 1 1 0 1 0
0 0 1 1 1 0 1 0 1 0 1 0 0 1 0 1
0 1 1 1 0 1 0 0 0 1 0 1 1 0 1 0
1 0 0 1 0 1 1 1 0 1 0 1
0 0 1 1 1 1 1 0 1 0 1 1
0 1 1 0 1 1 0 0 0 1 1 0
1 1 0 1 1 0 0 0 1 1 0 0
原始矩阵的四列中包含3,1,2和10的列。将其与7种可能的Hankel矩阵进行比较,为我们提供了两种可能性
1 1 1 0 0 1 1 1
1 1 0 1 1 1 1 0
1 0 1 0 1 1 0 0
0 1 0 0 1 0 0 0
现在,只有4种可能的排列可以将原始矩阵映射到每个矩阵:我们只有1个选择基于2和3 0的列,但2个选项用于1 0的列,还有2个具有1 0的行的选择。检查这些排列,我们看到以下Hankel矩阵是原始
的排列0 1 1 1
1 1 1 0
1 1 0 0
1 0 0 0
答案 1 :(得分:2)
这个问题的第一个答案是正确的,就是排列行和列不会改变行总和或列总和。
另一个简单的观察是,在Hankel矩阵中,两个连续行之间的行和的差异是-1,0或1,并且每种情况都给出了对行的约束。如果差值为0,则输入变量等于退出变量;否则我们知道哪个是0,哪个是1。
0 1 1 1
0 1 0 1
0 1 0 0
1 0 1 1
具有行和3,2,1,3。遵守差异要求的顺序是1 2 3 3和3 3 2 1,而wlog我们可以放弃反转,因为反转行和列排列只是旋转矩阵180度。因此,我们减少考虑四个置换矩阵(行和中3个的两个可能排序,列总和中的两个):
0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 1 1 1 1 0 1 0 1 1 1 1 1 1 0
1 1 0 1 0 1 1 1 1 1 1 0 0 1 1 1
我们实际上可以通过观察通过强制初始行具有和1和2来进一步进行分析,我们用3和3来约束列的顺序,因为
0 0 1 0
0 0 1 1
不是Hankel矩阵的有效初始两行。这种推理是否易于实现取决于您的编程范例。
请注意,在最坏的情况下,这种推理仍然不会将多项式数量的案例留给蛮力。
答案 2 :(得分:-2)
以下是一些想法。
行和列排列保留行和列总和:
1 0 1 0 - 2
0 0 0 1 - 1 row sums
1 0 0 0 - 1
1 1 1 0 - 3
| | | |
3 1 2 1
column sums
无论哪种方式排列行,行总和在某些排列中仍然是{2,1,1,3};列总和将保持不变。反之亦然。 Hankel矩阵及其排列将始终具有与列总和相同的行总和。这为您提供了一个快速测试,可以排除一组不可行的矩阵。
我认为Hankel矩阵总是可以通过这样的方式进行置换:行和列总和按升序,结果仍然是Hankel矩阵:
0 1 1 0 - 2 0 0 0 1 - 1
1 1 0 0 - 2 0 0 1 1 - 2
1 0 1 1 - 3 --> 0 1 1 0 - 2
0 0 1 0 - 1 1 1 0 1 - 3
| | | | | | | |
2 2 3 1 1 2 2 3
因此,如果矩阵可以置换为Hankel矩阵,那么它也可以置换为上升行和列和的Hankel矩阵。也就是说,我们可以通过仅测试行和列总和按升序排列的排列来减少测试所需的排列数。
我进一步假设对于任何Hankel矩阵,其中两行或更多行具有相同的和,列的每个排列具有匹配的行排列,这也产生Hankel矩阵。也就是说,如果对于列的一个排列存在Hankel矩阵,那么它对于列的每个排列都存在 - 因为我们可以简单地将相同的排列应用于相应的行并实现对称的结果。
结果是我们只需要测试行 或 列的排列,而不是行 和 列的排列
应用于原始示例:
1 0 1 0 - 2 0 0 0 1 0 1 0 0 - 1 0 0 0 1
0 0 0 1 - 1 1 0 0 0 0 0 0 1 - 1 0 1 0 0
1 0 0 0 - 1 --> 1 0 1 0 --> 0 0 1 1 - 2 --> 0 0 1 1 = Hankel!
1 1 1 0 - 3 1 1 1 0 1 0 1 1 - 3 1 0 1 1
| | | |
3 1 2 1 permute rows into| ditto | try swapping
ascending order | for columns | top 2 rows
我最后假定,每个Hankel矩阵中有多个行和列具有相同的总和,可以置换为另一个Hankel矩阵,其属性为当读取为二进制数时,这些行和列的顺序递增 - 从左到右读取行,从上到下读取列。那就是:
0 1 1 0 0 1 0 1 0 0 1 1
1 0 0 1 0 1 1 0 0 1 0 1 New
1 0 1 0 --> 1 0 0 1 --> 1 0 1 0 Hankel
0 1 0 1 1 0 1 0 1 1 0 0
Original rows columns
Hankel ascending ascending
如果这是真的(我还没有决定),那么我们只需要创建和测试任何给定输入矩阵的一个排列。该排列按行和列的顺序排列行和列,在等数和的情况下,按二进制数解释对它们进行排序。如果这个结果矩阵不是Hankel,那么没有任何排列可以使它成为Hankel。
希望能让你顺利进入算法!
0 0 1 0 0 0 1 0 0 0 0 1
0 1 0 1 0 1 0 1 0 1 1 0
1 0 1 1 --> 0 1 1 1 --> 0 1 1 1
0 1 1 1 1 0 1 1 1 0 1 1
(A) (B) (C)
1 1 0 1 0 1 0 0 0 0 1 0
1 0 1 0 1 0 0 1 0 1 0 1
0 1 0 0 --> 1 0 1 0 --> 1 0 0 1
1 0 0 1 1 1 0 1 0 1 1 1
(A) (B) (C)
注意:我建议二进制顺序(#4)仅用于行或列总和的tiebreak情况,而不是(#2)中排序的替代。