如何在n <= 900且a(i,j)= 0或a(i,j)= 1的n * n矩阵中找到每个a(i,j)的条目?

时间:2020-06-09 13:04:48

标签: java algorithm

假设我给了n个基本n=4矩阵,开始时全为零。

给出与每一行和每一列相关的总和。

例如0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

矩阵:

2, 2, 1, 1

给定的行总和:2, 0, 2, 2

给定的列总和:0 0 1 1 1 0 0 1 0 0 1 0 1 0 0 0

因此输出矩阵应类似于:

n=4

始终存在解决方案。 因此,对于0<=rowsum<=4 and 0<=columnsum<=4,{{1}}

2 个答案:

答案 0 :(得分:4)

您可以用贪​​婪的方法解决这个问题。

while not filled:
    find biggest unfilled row:
        fill in putting 1s in columns with largest sums

在您的情况下,您开始使用:

    2 2 0 2
  ----------
2 | _ _ _ _
2 | _ _ _ _
1 | _ _ _ _
1 | _ _ _ _

填充以下行之一:

    1 1 0 2
  ----------
2 | _ _ _ _
  | 1 1 0 0
1 | _ _ _ _
1 | _ _ _ _

填写另一个:

      1   1
  ----------
  | 1 0 0 1
  | 1 1 0 0
1 | _ _ _ _
1 | _ _ _ _

另外两个可以类似地填写:

  ----------
  | 1 0 0 1
  | 1 1 0 0
  | 0 1 0 0
  | 0 0 0 1

假设行值的总和与列值的总和匹配,并且0 <= value <= n与所有列值的总和匹配,此过程将始终有效。


更新:如评论中所指出,可能没有其他解决方案存在。您可以尝试填写一行并且没有足够的列来填充它,这一事实将是可以检测到的。

但是,如果遇到这样的障碍,那就没有解决办法了。

答案 1 :(得分:0)

Btilly的答案将为您服务。但是可以改进。您可以通过按降序对它们进行排序来进行预处理,而不是每次都找到最大和的行和列,但是重要的是保持它们的原始位置。您可以使用一个简单的类:

class SortedRow {
    int val;
    int originalIndex;
    public SortedRow(val, originalIndex) {
        this.val = val;
        this.originalIndex = originalIndex;
    }
}

然后对它们排序(rowVals和colVals是具有所需总和的数组):

public static void preprocess(int[] rowVals, int[] colVals){
    SortedRow[] rows = new SortedRow[n];
    SortedRow[] cols = new SortedRow[n];
    for (int i = 0; i < n; i++) {
        rows[i] = new SortedRow(rowVals[i], i);
        cols[i] = new SortedRow(colVals[i], i);
    }
    // Sort both arrays by val with some sorting algorithm of your choice - in descending order!
}

现在,您可以像Btilly建议的那样以贪婪的方式开始填充nxn矩阵,除非您不必每次都寻找最大的矩阵-您已经拥有了。在新课程的originalIndex字段中填写。

它将最坏情况的运行时间从三次改进为二次:预处理以O(nlogn)运行,如果您对n的值有一定的了解,甚至可以是线性的。填写矩阵的时间为O(n ^ 2)。