【发布时间】:2016-02-25 16:32:11
【问题描述】:
我正在尝试解决这个 spoj 问题http://www.spoj.com/problems/BYTESM2/
这是我迄今为止尝试过的代码,
#include <iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[101][101],Table[101][101]={0};
int pickStones(int i,int j,int n,int m,int sum)
{
int k,l,p;
int stones=0;
if(i>n||j>m||j<0)
return 0;
else if(i==n)
return Table[i][j]=sum;
else
{
if(Table[i][j]==0)
{
if(Table[i+1][j]==0)
Table[i+1][j]=pickStones(i+1,j,n,m,sum+a[i][j]);
if(Table[i+1][j-1]==0)
Table[i+1][j-1]=pickStones(i+1,j-1,n,m,sum+a[i][j]);
if(Table[i+1][j+1]==0)
Table[i+1][j+1]=pickStones(i+1,j+1,n,m,sum+a[i][j]);
stones=max(Table[i+1][j],Table[i+1][j-1]);
stones=(max(stones,Table[i+1][j+1]));
Table[i][j]=stones;
}
return Table[i][j];
}
}
int main() {
int t,n,m,l=0,h=0,max;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&a[i][j]);
max=a[0][0];
for(int i=0;i<m;i++)
if(a[0][i]>max)
{
max=a[0][i];
l=0;h=i;
}
printf("%d\n",pickStones(l,h,n,m,0));
}
return 0;
}
如果我摆脱动态编程 Table[][] 数组并将 `pickStones() 的结果存储在变量中并将问题实现为普通递归,我会得到正确的答案,但我不知道其中的重叠子问题在哪里以及如何存储它们以避免再次计算。
【问题讨论】:
-
我想你误解了什么是动态规划。维基百科关于 levenshtein distance 的条目特别清楚:DP 只是一个递归,没有“表”。不幸的是,幼稚的实现通常永远运行,因此在一个有效的实现中,先前计算的子问题的结果存储在一个表中。在这种情况下,没有递归调用,表是从先前计算的条目中填充的。您正在混合这个想法及其可能的实现之一。
-
DP 只是一个递归,没有“表”。不幸的是,幼稚的实现通常永远运行,因此在一个有效的实现中,先前计算的子问题的结果存储在一个表中。 正是,这就是我想要实现的,将预先计算的结果存储在 Table[][]大批。问题是我找不到重叠的子问题并存储结果,尽管我可以通过简单的递归得到答案。
-
能否请您发布没有“表格”的“正确”代码?
-
您的“表格”的每个单元格都将包含一个数字,该数字是哈利从该单元格开始到最后一行的任何路径上可以拾取的最大石头数。最初所有单元格都为零。您可以在不移动的情况下填充哪些单元格?答案:最后(h-th)行的所有单元格。现在,给定最后一行的值,您可以通过取三个可访问单元格中的最大值加上该单元格上的石头数来计算第 h-1 行的数量。子问题是你可以从第 h 行捡起的石头的数量......但这已经填好了,所以没有递归。然后你倒退到第一行。
标签: c++ algorithm dynamic-programming