假设我给了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}}
答案 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)。