我试图解决一个面试问题:
给定n * n的矩阵。每个单元格包含0,1,-1。 0表示有 没有钻石,但有一条路。 1表示有钻石 有路径的位置 -1表示路径被阻止。现在你从0,0开始到达最后一个细胞&然后返回0,0收集最大值 钻石。在前往最后一个单元格时,您只能向右和向下移动。 返回时,您只能向左和向上移动。
我已经解决了这个问题,但我不确定这是否是最佳解决方案。我正在做的是
有关正确性的任何建议吗? 我已经编写了代码,如果需要,我将分享。
答案 0 :(得分:4)
您的算法不正确。 这是一个反例:
<table border="1">
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
</table>
从上到下的最大路径将收集5颗钻石,可能是这样的:
<table border="1">
<tr>
<td>*</td>
<td>*</td>
<td>_</td>
</tr>
<tr>
<td>_</td>
<td>*</td>
<td>*</td>
</tr>
<tr>
<td>_</td>
<td>_</td>
<td>*</td>
</tr>
</table>
但是你的第二次迭代只能再收集2次。
因此,您的算法将返回最大值7。
但是有一个解决方案,你可以用它收集8。
E.g。如果你的路径看起来像这样:
<table border="1">
<tr>
<td>*</td>
<td>_</td>
<td>_</td>
</tr>
<tr>
<td>*</td>
<td>*</td>
<td>_</td>
</tr>
<tr>
<td>_</td>
<td>*</td>
<td>*</td>
</tr>
</table>
答案 1 :(得分:3)
您可以使用动态编程。 你需要填充矩阵的大小[2 * n-1,n,n] 其中DP [A,B,C]等于对角线(或总路长度)A的最佳结果,第一路进入位置B,第二路进入位置C.
您从DP [0,0,0]开始并结束到DP [2 * n-1,0,0] 答案是DP [2 * n-1,0,0]
DP [l,i,j] = MAX(DP [l-1,i,j],DP [l-1,i-1,j],DP [l-1,i,j-1] ,DP [l-1,i-1,j-1])+ Diamond [i,li] + Diamond [j,lj],如果i等于j,则由Diamond [j,lj]减少。
跳过所有无法通行的地方。
总复杂度为O(N ^ 3)
答案 2 :(得分:0)
“您已经从0,0开始到达最后一个单元格,然后又返回到0,0”
==“您从0,0开始两次到达最后一个单元格”
和
d:总距离
x1:第一个x位置
x2:x位第二秒
y1:d-x1 //可以省略
y2:d-x2 //可以省略
dp [d] [x1] [x2]:从单元(0,0)到达单元(x1,y1)并从单元(0,0)到达单元(x2,y2)的最大钻石数量>