生成二进制矩阵的算法

时间:2016-08-25 07:01:00

标签: algorithm greedy binary-matrix

给定两个输入数组[R1,...,Rn]和[C1,...,Cn]。我们想要创建一个二进制矩阵A(大小为nxn),使得A的列i中的元素之和为Ci,并且A的行j中的元素之和为Rj。

我尝试使用贪婪算法填充:从左到右填充1并递减Ci并对每行执行此操作。但是,它没有用。 (另外,我尝试按递减顺序对行和列进行排序,但仍然没有工作)

1 个答案:

答案 0 :(得分:6)

这可以使用最大流量来解决。 LightOJ上提供了类似(更难的版本)问题,我的代码为reference

这是解决方案。

我们将首先创建一个二分图。将行数设为no_rows,列数为no_cols

现在创建no_rows + no_cols个节点。安排左边的第一个no_rows节点(这将形成我们的二分图的一个“副”)。让我们将这些节点编号为l1, l2, ..., lno_row

同样安排右边的最后no_cols个节点(将形成第二个“partite”)。让这些编号为r1, r2, ... , rno_cols

现在为所有lirj添加1 <= i <= no_rows1 <= j <= no_cols之间的边 li,从左到右,容量为1.

现在创建一个源(S)和一个接收器(T)。将从源定向的单位容量边缘添加到左侧的每个顶点。

类似地,将从右侧每个顶点定向的单位容量边缘添加到接收器。

现在只需在此图表中找到最大流量。现在,如果某个rj和某些(i, j)之间存在流,则表示单元格(S, l)将为1,否则为0。

注意:为确保存在这样的二进制矩阵,请确保每个(r, T)边和li边都完全填满。

编辑:以下是C ++ ideone

中Dinic的实现

编辑2:将源连接到任何Ri的边的容量为R(其中ri是指示行总和的给定输入数组)。同样,连接T到汇Ci的边的容量为C(其中const string baseUri = ""; // base url of API const string setDealFlagUri = "Deals/SetDealFlag"; 是输入中指定列总和的数组)