hdu 2084 数塔
来源:互联网 发布:php清除cookie 编辑:程序博客网 时间:2024/06/05 00:39
题目:点击打开链接
题目大意:数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
分析:经典的动态规划问题,也是做的第一道动态规划问题,因为初学,在刘汝佳的书上也有详细讲解,在这里好好分析一下吧。
因为是从顶层走到底层,没经过一个位置所走的数字和就不一样,我们用d[I][j]来存储这个位置的状态,即总共走的路程,从上到下,确定的一点就是顶点,所以这个问题就等价于求d[1][1],从(i,j)点出发后只能向下或右下走,要求经过和最大,所以要走d[I+1][j]和d[I+1][j+1]大的那个,所有有状态转移方程d[I][j]=a[I][j]+max(d[I+1][j],d[I+1][j+1]),其中a数组存储的是(i,j)这点的值。
状态方程有了之后就好办了,我们可以有三种计算方法。
法一:递归计算:
int solve(int i,int j){ return a[i][j]+(i==n?0:max(solve(i+1,j),solve(i+1,j+1)));需要注意边界,当I==n时,I+1,j+1会越界}
这样做时间效率很低,因为会重复计算一些状态(可能做了一半的无用功)
为了避免访问过的状态不会重新访问,我们需要把状态访问结果保存在d数组中,在递归的时候判断是否已经放问过,这种方法称为记忆化搜索
法二:记忆化搜索:数组d需要初始化memset(d,-1,sizeof(d))fa
int solve(int i,int j){ if(d[i][j]>=0)return d[i][j]; return d[i][j]=a[i][j]+(i==n?0:max(solve(i+1,j),solve(i+1,j+1)));}
法三:递推计算:
因为需要求出d[1][1],所以我们从底层逆推,状态转移方程d[I][j]=a[I][j]+max(d[I+1][j],d[I+1][j+1]),我们要初始化边界d[n]
for(int j=1;j<=n;j++)d[n][j]=a[n][j]; for(int i=n-1;i>=1;i--) for(int j=1;j<=i;j++) d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]);
代码:
#include<iostream>#include<string.h>#include<algorithm>using namespace std;int T,n,a[105][105],d[105][105];int main(){ cin>>T; while(T--){ cin>>n; memset(d,0,sizeof(d)); for(int i=1;i<=n;i++){ for(int j=1;j<=i;j++) cin>>a[i][j]; } for(int i=n;i>=1;i--){ //也可以直接从n层开始因为d数组已经初始化0,d[n+1]层都是0,不影响 for(int j=1;j<=i;j++) d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]); } cout<<d[1][1]<<endl; } return 0;}
0 0
- HDU 2084 数塔
- hdu 2084 数塔
- hdu 2084 数塔
- hdu 2084 数塔
- hdu 2084 数塔
- HDU 2084 数塔
- hdu 2084 数塔
- HDU 2084 数塔
- HDU 2084 数塔
- hdu 2084 数塔
- hdu 2084 数塔
- HDU 2084(数塔)
- HDU 2084 数塔
- HDU-2084数塔
- HDU 2084 数塔
- hdu 2084 数塔
- hdu--2084--数塔
- HDU 2084 数塔
- 作业
- C++ 对象指针
- apk 签名
- Connect the Cities 3371
- 使命栈(stack)实现一个简易的四则运算计算器
- hdu 2084 数塔
- 记录一些第三方
- MCS 最小生成树#2 Kruskal
- service sshd restart sshd unrecognized service
- 黑马程序员——一维数组指针探究
- 卸载mysql5.1后再次安装不成功的解决方法
- zoj1372Networking(模板题)
- 知乎-国外知名 IT 企业是如何做测试的?
- UINavigationController的代理方法