我们有一个N * N网格。我们最初位于网格的左上角。网格的每个方格都有一些附加值,也就是说,如果有人到达那个方格,他就会以等于广场附加值的美元赢得金额。现在,法律行动是迈向正确的一步,也是迈向底层的一步。我们必须在一条路径中到达网格的右下角,这样我们才能最大化赢得的金额。显然我们必须留在网格中,不能徘徊。 我通过一种贪婪的方法开始了这个问题,在每一步我们都会看到在正方形下方的直接正方形和直接正方形,并且在每一步中选择具有更高值的正方形。但这并没有给出正确的结果。例如,在以下网格中,
{ 6, 9, 18, 1 }
{ 2, 10, 0, 2 }
{ 1, 100, 1, 1 }
{ 1, 1, 1, 1 }
这里我的算法给出了最大值路径
6 -> 9 -> 18 -> 1 -> 2 -> 1 -> 1
总计为37,但我们可以在路径上赚得更多
6 -> 9 -> 10 -> 100 -> 1 -> 1 -> 1
总计128.你能帮助我建立一个合适的算法吗?我还没有对此进行编码,因为无论如何它都会产生错误的输出。我不知道如何在没有蛮力的情况下解决这个问题,包括查看所有路径中的值不包含最小值的正方形,然后找到最大值。
#include <iostream>
#include <queue>
using namespace std;
int main()
{ int n; cin >> n;
int a[n+1][n+1], b[n+1][n+1];
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
{
cin >> a[i][j]; b[i][j]=a[i][j];
}
}
queue <int> q; int u,v,m=0;
q.push(0);q.push(0);
while (q.size()!=0)
{
u=q.front(); q.pop(); v=q.front(); q.pop();
if (v<n-1)
{
m=b[u][v]+a[u][v+1];
if (m>b[u][v+1])
{ b[u][v+1]=m; }
q.push(u);q.push(v+1);
}
if (u<n-1)
{
m=b[u][v]+a[u+1][v];
if (m>b[u+1][v])
{ b[u+1][v]=m; }
q.push(u+1);q.push(v);
}
}
cout << b[n-1][n-1];
return 0;
}
答案 0 :(得分:2)
可以通过以下方法解决问题。位置(i,j)
的每个单元格都会与值val(i,j)
相关联,这是从位置{{1}开始,通过所描述的合法移动(从下到右)到达它可能达到的最大总值}。位置(0,0)
的值是网格中的值,在每个(0,0)
的续集中称为grid(i,j)
。我们获得了以下的复发关系
i, j in {0,...,N-1}
我们假设val(i,j) = grid(i,j) + max{ val(i-1,j), // path coming from upper cell
val(i,j-1) // path coming from left cell
}
之外的指数产生负无穷大的值并且从未真正使用过。递归关系是有效的,因为到达一个小区最多有两种情况,即来自其上邻居或其左邻居(边界处的小区除外,可能只能从一个邻居到达)。
有效评估{0,...,N-1} * {0,...N-1}
的关键是组织序列中的值计算,以便已经评估了所有需要的邻居;这可以通过在尚未计算val
的最左边的单元格处连续凝视计算来完成,并且以向上 - 向右的方式从那里开始工作直到到达顶行。这将被迭代,直到评估位置val
,从而产生所需的结果。
如果还需要val(N-1,N-1)
的特定路径,则必须使用回溯或某些辅助数据结构来存储如何计算上述递归关系中的值,即哪个项产生最大值。 / p>
修改的
或者,评估可以从左到右按行进行,也具有所需的属性,即已经计算了递归关系的所有必要值;这显然更容易实现。在任何一种情况下,运行时绑定都是(N-1,N-1)
。
答案 1 :(得分:0)
实际上这是一个可以使用动态编程解决的问题。您只需要调整算法来计算编辑距离,以便获得不同的奖励。 该算法在例如https://web.stanford.edu/class/cs124/lec/med.pdf
中描述基本的想法是,从顶部开始,无论何时现在它的相邻(顶部,左侧)场都填充正方形。 您在字段中输入的值是两个邻居中较高者的值和当前字段的值。当你到达右下角时,你只需要沿着这条路走。