给出行和列总和,查找二进制矩阵是否存在

时间:2014-01-08 02:22:14

标签: math tomography-reconstruction

如何确定是否可以构造具有给定行和列总和的二进制矩阵。

输入:

第一行输入包含两个数字1≤m,n≤1000,矩阵的行数和列数。下一行包含m个数字0≤ri≤n - 矩阵中每行的总和。第三行包含n个数字0≤cj≤m - 矩阵中每列的总和。

输出:

如果存在m-by-n矩阵A,则输出“YES”,每个元素为0或1.否则为“否”。

我尝试阅读有关断层扫描算法但无法找到答案,因为所有与断层扫描算法相关的论文都非常复杂。

有人可以帮帮我..

1 个答案:

答案 0 :(得分:10)

我已经成功实现了使用基于network flow的建模为R随机生成这样的矩阵。我打算有一天写下这些想法,但还没有找到时间。为此重新研究,我在Miklós和Podani的Randomization of Presence–absence Matrices: Comments and New Algorithms中读到了:

  

Havel - Hakimi定理(Havel 1955Hakimi 1962)表明存在矩阵 X n ,m 的0和1的行总计 a 0 =( a 1 a 2 ,..., a n )和列总数 b 0 =( b 1 b 2 , ..., b m ),以便 b i b i +1 每0 <&lt; i &lt; m 当且仅当另一个矩阵 X n -1, m 为0时和1的行总计 a 1 =( a 2 a 3 ,..., a n )和列总计 b 1 =( b 1 -1, b 2 -1,..., b a 1 -1, b a 1 +1 ,..., b m )也存在。

我想这应该是以递归方式决定你的问题的最佳方法。

用我自己的话说:选择任何一行,将其从总计列表中删除。调用删除号码 k 。还要使用大的总和从 k 列中减去一个。您获得较小矩阵的描述,并递归。如果在任何时候您没有具有非零和的 k 列,则不存在这样的矩阵。否则,您可以使用反向过程递归地构建匹配矩阵:获取递归调用返回的矩阵,然后再添加一行 k ,并将其放置在您最初减去其中一个计数的列中。

实施

bool satisfiable(std::vector<int> a, std::vector<int> b) {
  while (!a.empty()) {
    std::sort(b.begin(), b.end(), std::greater<int>());
    int k = a.back();
    a.pop_back();
    if (k > b.size()) return false;
    if (k == 0) continue;
    if (b[k - 1] == 0) return false;
    for (int i = 0; i < k; i++)
      b[i]--;
  }
  for (std::vector<int>::iterator i = b.begin(); i != b.end(); i++)
    if (*i != 0)
      return false;
  return true;
}