青蛙问题

dwen20 2008-05-02 05:27:25
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
(图1)

一只青蛙从如图1所示的三角形顶端向底边跳去,青蛙每次只能向下跳一格,落到到最近的左下方或右下方的一点。写一个程序,帮助青蛙找出由顶点到底边的一条路径,使得这条路径上的所有数字之和S最大。

大家说说有什么好的解法吧!
...全文
367 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
freeCodeSunny 2008-05-04
  • 打赏
  • 举报
回复
一个数组是可以做出来的,但是当N很大时就 慢的算不出来了,N=100你就要等的花儿都谢了
代码如下
#include <iostream>
#define MAX 100
using namespace std;

int d[MAX][MAX];
int n;
int maxsum(int r,int j)
{
if(r==n)
return d[r][j];
int nsum1=maxsum(r+1,j);
int nsum2=maxsum(r+1,j+1);
if(nsum1>nsum2)return nsum1+d[r][j];
return nsum2+d[r][j];
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i)
for(int j=1;j<=i;++j)
cin>>d[i][j];
cout<<maxsum(1,1);
}
只要上面没有打错,应该是对的,尽量用DP吧!那样要快的多
可口可乐 2008-05-03
  • 打赏
  • 举报
回复
只能说你对动态规划的理解出错了,
medie2005的代码没有什么问题,你仔细读读
dwen20 2008-05-03
  • 打赏
  • 举报
回复
谢谢啦,连代码都给贴出来了。
我当时也是这么想的,但是我还是得指出其中的一个错误,因为一开始我也犯了这个错误。

所有路径的数目应该是2^(N-1),而不是N,不然的话,加数就很容易定位了。正因为是2^(N-1),才使得
加法很复杂。并且我发现,如果有M条路径,那么第一层求出的是S[0],第二层求出的是S[0]和S[M/2],
第三层是S[0],S[M/4],S[M/2],S[M/2+M/4]....第N层是第N-1层已有的值“并(合并)”上第N-1层相邻两值
的中点位置值 之后得到的数值...

因此,这道题的难点无疑就在于怎么找出一个规律(如果存在一个合适的规律的话),从而更加方便的求和。

另外,两个数组一个用作保存实际数值,另一个用于保留上一次的值时间开销会很大。
如果我们轮流使用,就不用保存上一次的值了,这样最多增加一次判断就可以实现:使第一次用数组A,第二次
就把A里的值加上当前输入的值直接赋给数组B,第三次再把B数组的值加上当前输入值再赋给数组A。
也就是奇数层用A,偶数层用B
dwen20 2008-05-03
  • 打赏
  • 举报
回复
一个数组?
能否给点提示?
dwen20 2008-05-03
  • 打赏
  • 举报
回复
看来小弟确实理解错了,唉,当时动态规划没有好好学,理解不够深入。
medie2005的代码的确是正确的,刚刚实践了一下。
谢谢各位啦!
medie2005 2008-05-03
  • 打赏
  • 举报
回复
确实,我给的代码并不是最高效的,代码中S[0]与S[1]之间的复制操作的确可以省略,这个没有疑问,但是,这个复制操作是不会耗太多时间的。当然,如果你的目标是作top User,那就另说了。
另外,其实可以只用一个长度为n的数组来做。
linux_and_unix 2008-05-03
  • 打赏
  • 举报
回复
我都看傻眼了。
chengzhe 2008-05-02
  • 打赏
  • 举报
回复
动态规划
medie2005 2008-05-02
  • 打赏
  • 举报
回复
int n, temp, i, j;
cin>>n;
int *S[2];
S[0]=new int[n]; S[1]=new int[n];
for( j=0; j<n; ++j )
S[0][j]=0;
cin>>S[0][0];
for( i=1; i<n; ++i ){
for( j=0; j<=i; ++j ){
cin>>temp;
if( j==0 )
S[1][0]=S[0][0]+temp;
if( j==i )
S[1][j]=S[0][j-1]+temp;
else
S[1][j]=max( S[0][j], S[0][j-1] )+temp;
}
for( j=0; j<=i; ++j )
S[0][j]=S[1][j];
}
int result=S[1][0];
for( i=1; i<n; ++i )
result=max(S[1][i],result);
cout<<result<<endl;
delete []S[0]; delete []S[1];
可口可乐 2008-05-02
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 dwen20 的回复:]
我当时也考虑只用两个数组就够了,但是不知道相加的时候怎么定位加数。
[/Quote]
2楼不是写的很清楚了,我写的有点问题,改一下
dp[i][j]=max(dp[i-1][j-1], dp[i-1][j])+element[i][j]
dwen20 2008-05-02
  • 打赏
  • 举报
回复
恩!
动态规划是没有异议的,其实这道题我没有写详细,这是一道ACM的题目,关键在于它要求输入形式为
3
1
2 4
3 4 5
第一行表示层数,下面依次是每行数据。
输出为S值
时间限制是1000Ms,内存开销也尽量越小越好。

我当时也考虑只用两个数组就够了,但是不知道相加的时候怎么定位加数。
medie2005 2008-05-02
  • 打赏
  • 举报
回复
动态规划.
设List[i][j]表示三角形中第i层第j个格子中的数据.
记S(level,k)表示青蛙从顶端跳到第level层中的第k个格子的最小路径和.
那么,我们有:
S(level+1,k)=max( S(level,k-1), S(level,k) ) + List[level+1][k]; 1<k<level+1
S(level+1,1)=S(level,1)+List[level+1][1];
S(level+1,level+1)=S(level,level)+List[level+1][level+1];

假设三角形有n层,那么,我们现在要求max(S(n,i)) (1<=i<=n).我们可以先将所有的S(t,j) (1<=j<=t<=n)全部求出来,显然,总共有1+2+3+...+n=n*(n+1)/2个S(t,j).因此,我们按照上面列出来的递归关系,自底而上求解各个S(t,j),于是,时间复杂度是O(n^2),空间复杂度是O(n^2)的.
可口可乐 2008-05-02
  • 打赏
  • 举报
回复
典型的动态规划题。
设dp[i][j]为第i行第j个元素能得到的最大和,
则dp[i][j]=dp[i-1][j-1]+dp[i-1][j]; //这儿注意检查j-1,j是否越界

实际上某行的和只与上一行相关,用个dp[2][N]就够了

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧