我有2D数组,其中每个元素都是O
或Non Zero
,我必须收集所有1
个元素。为此,我将雇用一名工人
`0` - dead coconut tree
`Non Zero` - living tree
一名工人开始在活树上收割,并沿着四个主要方向之一(即北,南,东或西)的直线树木继续收割。当满足下列条件之一时,工人停止收获椰子
问题:
当我知道这是Maximum Matching Problem
时,我很震惊,我不知道它是怎么回事。
以下是使用索引标记水平和垂直条带的代码
m=1;
for (int i=0; i<r; i++) {
int j = 0;
while (j < c && a[i][j] < m) j++;
while (j < c) {
while (j < c && a[i][j] >= m) {
h[i][j] = hcnt;
j++;
}
hcnt++;
while (j < c && a[i][j] < m) j++;
}
}
int vcnt = 0;
for (int j=0; j<c; j++) {
int i = 0;
while (i < r && a[i][j] < m) i++;
while (i < r) {
while (i < r && a[i][j] >= m) {
v[i][j] = vcnt;
i++;
}
vcnt++;
while (i < r && a[i][j] < m) i++;
}
}
所以我的问题是如何添加边缘以及为什么它是最大匹配问题,有人可以解释这背后的直觉,为什么最大匹配可以解决这个问题。
Original Question
以下代码添加边缘。我不知道我们是如何添加边缘的,为什么它正在工作
int s = 0, t = hcnt + vcnt + 1;
for (int i=0; i<hcnt; i++) addEdge(s, i+1, 1);
for (int i=0; i<r; i++) {
for (int j=0; j<c; j++) if(a[i][j] >= m) {
addEdge(1 + h[i][j], 1 + hcnt + v[i][j], 1);
}
}
for (int i=0; i<vcnt; i++) addEdge(1 + hcnt + i, t, 1);
答案 0 :(得分:1)
这个想法如下:我们需要采取一些垂直和水平线,以便覆盖所有树木,并最大限度地减少拾取的线条数量。
带树的每个单元格成为图形中的边缘。每条垂直线成为图形左侧部分的顶点,每条水平线成为右侧部分的顶点。现在问题相当于在此图中找到顶点覆盖。最大匹配的大小等于任何二分图中顶点覆盖的大小(它或多或少是众所周知的定理)。