#401. 【dp开始】数字三角形

#401. dp开始】数字三角形

题目描述:

观察下面的数字金字塔。

7

3  8

8  1  0

2  7  4  4

4  5  2 6  5

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

 在上面的样例中, 3  8  7  5 的路径产生了最大

主题思路:

这一题就是一道十分典型的DP(动态规划)思想的题目。我们也许会问,DP是什么???DP是一种思想,而不是一种算法,这与贪心是一个道理。DP也是通过一群局部最优解得到一个全局最优解,但也有求方案数的DP。DP与贪心不同,DP是需要划分阶段并写方程的。不过DP也有两种形式:递推与记忆化搜索(记忆化搜索一般常数较大,比较慢)DP的具体思想都是要做题做出来的,所以得看题。DP一般要满足两个特性:最优性与无后效性。最优性即要满足最优解性质,保证每一步都是最优的。无后效性即要满足求解某个阶段只会与上一个阶段有关,或者说一个阶段求完后,不会对前面造成影响。划分阶段即设定数组,这个数组的某一位表示什么情况下的最优解,最终推得全局解。找出这个阶段与上一个阶段的关系,即如何从这个阶段的解推得下一个阶段解(以上对这一题来说其实都是废话)

这一题就是要从金字塔的底层开始逆推,然后求出整体的全局最优解。真是道简单而典型的DP题目。这样说我们可能都不明白,我们来从题目样例操作一遍:

最顶层:7

第二层:3  8

第三层:8  1  0

第四层:2  7 4  4

最底层:4  5 2  6  5

从最底层第一个开始搜索,每次搜索a【i】【j】和a【i】【j+1】,从中选出一个较大数,并与a【i-1】【j】相加。就拿最底层第一个4来说吧,4和5比较,显然是5比较大,然后把第四层第一个2加上较大数5,得到了6。不断进行这种操作。最后得到一个“加工”过的数组如下:

最顶层:30

第二层:23  21

第三层:20  13  10

第四层:7   12  10  10

最底层:4   5   2   6   5

然后我们就会发现最顶层的那个数就是我们要得到的最大值,这就是本题的最优解。这题完全可以使用过程或者函数解决,但因为鄙人是小蒟蒻一只,并且这一题不用考虑会不会超内存,不用优化,所以我决定用上最简单粗暴的二重循环来解决这道DP

代码如下:

#include<bits/stdc++.h>

using namespace std;

int a[1001][1001]={0},b[1001][1001]={0},i,j,r,t;

int main()

{

   cin>>r;

   for(i=1;i<=r;i++)

   for(j=1;j<=i;j++)

   cin>>a[i][j];

   for(i=r-1;i>=1;i--)

   for(j=1;j<=i;j++)

   {

        if(a[i+1][j]>a[i+1][j+1])t=a[i+1][j];

        if(a[i+1][j]<a[i+1][j+1])t=a[i+1][j+1];

        a[i][j]+=t;

   }

   cout<<a[1][1];

}然后我们就会惊奇的发现:居然没AC?!

然后仔细思考,如果比较的两个数相等,那么T就不会改变,所以应该再加一个IF语句判断是否相等。真让人头秃。。。。。。

终极程序:

#include<bits/stdc++.h>

using namespace std;

int a[1001][1001]={0},b[1001][1001]={0},i,j,r,t;//最好使用全局变量

int main()

{

      cin>>r;

      for(i=1;i<=r;i++)

      for(j=1;j<=i;j++)

      cin>>a[i][j];//读入是一个三角形方阵

      for(i=r-1;i>=1;i--)

      for(j=1;j<=i;j++)

      {

           if(a[i+1][j]>a[i+1][j+1])t=a[i+1][j];//判断哪个比较大

           if(a[i+1][j]<a[i+1][j+1])t=a[i+1][j+1];//ctrl+c方便一点

 if(a[i+1][j]==a[i+1][j+1])t=a[i+1][j+1];//判断是否相等

           a[i][j]+=t;//上一层加上较大数

      }

      cout<<a[1][1];//输出最顶层的那一个数(全局最优解)

}

    终于AC,不容易啊!!!这真是道好题。。。DP就是要细心。。。#401. dp开始】数字三角形

题目描述:

观察下面的数字金字塔。

7

3  8

8  1  0

2  7  4  4

4  5  2 6  5

写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。

 在上面的样例中, 3  8  7  5 的路径产生了最大

主题思路:

这一题就是一道十分典型的DP(动态规划)思想的题目。我们也许会问,DP是什么???DP是一种思想,而不是一种算法,这与贪心是一个道理。DP也是通过一群局部最优解得到一个全局最优解,但也有求方案数的DP。DP与贪心不同,DP是需要划分阶段并写方程的。不过DP也有两种形式:递推与记忆化搜索(记忆化搜索一般常数较大,比较慢)DP的具体思想都是要做题做出来的,所以得看题。DP一般要满足两个特性:最优性与无后效性。最优性即要满足最优解性质,保证每一步都是最优的。无后效性即要满足求解某个阶段只会与上一个阶段有关,或者说一个阶段求完后,不会对前面造成影响。划分阶段即设定数组,这个数组的某一位表示什么情况下的最优解,最终推得全局解。找出这个阶段与上一个阶段的关系,即如何从这个阶段的解推得下一个阶段解(以上对这一题来说其实都是废话)

这一题就是要从金字塔的底层开始逆推,然后求出整体的全局最优解。真是道简单而典型的DP题目。这样说我们可能都不明白,我们来从题目样例操作一遍:

最顶层:7

第二层:3  8

第三层:8  1  0

第四层:2  7 4  4

最底层:4  5 2  6  5

从最底层第一个开始搜索,每次搜索a【i】【j】和a【i】【j+1】,从中选出一个较大数,并与a【i-1】【j】相加。就拿最底层第一个4来说吧,4和5比较,显然是5比较大,然后把第四层第一个2加上较大数5,得到了6。不断进行这种操作。最后得到一个“加工”过的数组如下:

最顶层:30

第二层:23  21

第三层:20  13  10

第四层:7   12  10  10

最底层:4   5   2   6   5

然后我们就会发现最顶层的那个数就是我们要得到的最大值,这就是本题的最优解。这题完全可以使用过程或者函数解决,但因为鄙人是小蒟蒻一只,并且这一题不用考虑会不会超内存,不用优化,所以我决定用上最简单粗暴的二重循环来解决这道DP

代码如下:

#include<bits/stdc++.h>

using namespace std;

int a[1001][1001]={0},b[1001][1001]={0},i,j,r,t;

int main()

{

   cin>>r;

   for(i=1;i<=r;i++)

   for(j=1;j<=i;j++)

   cin>>a[i][j];

   for(i=r-1;i>=1;i--)

   for(j=1;j<=i;j++)

   {

        if(a[i+1][j]>a[i+1][j+1])t=a[i+1][j];

        if(a[i+1][j]<a[i+1][j+1])t=a[i+1][j+1];

        a[i][j]+=t;

   }

   cout<<a[1][1];

}然后我们就会惊奇的发现:居然没AC?!

然后仔细思考,如果比较的两个数相等,那么T就不会改变,所以应该再加一个IF语句判断是否相等。真让人头秃。。。。。。

终极程序:

#include<bits/stdc++.h>

using namespace std;

int a[1001][1001]={0},b[1001][1001]={0},i,j,r,t;//最好使用全局变量

int main()

{

      cin>>r;

      for(i=1;i<=r;i++)

      for(j=1;j<=i;j++)

      cin>>a[i][j];//读入是一个三角形方阵

      for(i=r-1;i>=1;i--)

      for(j=1;j<=i;j++)

      {

           if(a[i+1][j]>a[i+1][j+1])t=a[i+1][j];//判断哪个比较大

           if(a[i+1][j]<a[i+1][j+1])t=a[i+1][j+1];//ctrl+c方便一点

 if(a[i+1][j]==a[i+1][j+1])t=a[i+1][j+1];//判断是否相等

           a[i][j]+=t;//上一层加上较大数

      }

      cout<<a[1][1];//输出最顶层的那一个数(全局最优解)

}

    终于AC,不容易啊!!!这真是道好题。。。DP就是要细心。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值