在二维空间中有一个N*M点的网格。可以将物品放置在点(x,y)上,但是点(x+2,y-2)、(x-2,y-2)、(x-2,y+2)或(x+2,y+2)不能有其他物品。此外,格子中还有几个点被卡住了,即这些点无法放置物品。
那么如何找到可以放置在网格中的最大物品数量?
那么如何找到可以放置在网格中的最大物品数量?
如果没有这些阻塞点,最佳的打包方式是放在列上。
(a + 0), (a + 3), (a + 6), ..., (a + 3*n)
无论在这些列的哪个位置存在一个块,都不能进行改进。如果一个块在 (x, y) 的某一列上,那么你可以在点 (x+2, y-2) 和 (x-2, y-2) 上放置它。因此,请遍历所有的列,并尝试将它们放置在最少数量的块上。(注意,之前是说最大化。我昨晚只睡了3个小时)
检查这个过程需要 n*m 步骤。
dp[i, 0] = dp[i - 1, 0] + dp[i - 1, 1] <- no 1 at i
dp[i, 1] = 2 * dp[i - 2, 0] <- we MUST have 0 at i - 2, but i - 1 can have whatever
=> if i is blocked dp[i, _] = dp[i - 1, _]
例子:
n = 3
brute force solutions:
000
010
100
001
110
011
=> 6
dp[0, 0] = 1 dp[0, 1] = 0
dp[1, 0] = 1 dp[1, 1] = 1
dp[2, 0] = 2 dp[2, 1] = 2
dp[3, 0] = 4 dp[3, 1] = 2
=> dp[3, 0] + dp[3, 1] = 6
O(lines*columns)
的时间复杂度内填充您的dp矩阵即可。我认为将网格视为一个环面是很形象的,即边缘会“环绕”(上下->左右),这样你就可以忽略边缘情况。当N和M很大时,这是一个很好的近似。
在环面上,每个点必然会阻挡另外两个点的存在,但你可以重叠排除区域,即一个点的(x+2, y-2)
也可以是另一个点的(x+2, y-2)
。因此,你可以实现的最大填充率是1/2。这可以通过交替的列条纹来实现:2个完整的列,2个空列,2个完整的列等。
我会留下角落情况(M不是4的倍数)。
在非环面的网格上,你有两个考虑因素。首先,你可以直接从网格边缘开始填满整个列。其次,你可以完全填充底部两行(“底部”是y最小的位置)。因此,你可以实现略高于1/2的填充率,但是随着尺寸趋近于无穷大,你仍然得到1/2。
FF..FF..FF..FF
(F
= 充满点的列,.
= 空列(即堵塞位置))。所有行都相同。 - Adam