The Triangle
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 41507 | Accepted: 25104 |
Description
7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1)
Input
Your program is to read from standard input. The first line contains one integer N: the number of rows in the triangle. The following N lines describe the data of the triangle. The number of rows in the triangle is > 1 but <= 100. The numbers in the triangle, all integers, are between 0 and 99.
Output
Your program is to write to standard output. The highest sum is written as an integer.
Sample Input
5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
Sample Output
30
Source
问题分析:
上述问题是一道典型的动态规划(DP)问题,动态规划和递归差不多,只不过比递归要难于理解,但在节省时间角度上,我们经常舍弃递归而采取动态规划的方法来处理问题。动态规划其实就是递推,下面我们来总结下什么问题适合递归,什么问题适合递推。对于一类问题,具有如下特征时,经常采取递归:
问题具有某种可借用的类同自身的子问题描述的性质;某一有限步的子问题(也称本原问题)有直接的解存在;最终有有结果返回给次外层。
注意:递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
通常我们对于一些问题会采用动态规划的递推来处理,比如下面这个问题:
对于连续输入的一串整数,找出它们当中和最大的一串子串(子串是连续的)。
eg:4,-5,3,2,-1,-3,5
其中最大的子串为(3,2,-1,-3,5),值为6。
算法思想:把问题分解为若干个小问题,每个小问题都可以用一个相同的算法求解,从而利用子问题的解来得到原问题的解。
子问题:从第一个数据开始分段,并把第一个数的值作为maxsum,来一个数就和前面的数加和,如果和不小于0就继续,然后进行和maxsum重新比较,如果大于maxsum就给maxsum赋新的值,如果不大于,还保留maxsum的值;如果来一个数和前面的数加和后小于0,则重新开始下一段。
代码如下:
#include #include #define LEN 1000 int main(void) { int sum,sum_max; int a[LEN]; int i,n; while(scanf("%d",&n),n != 0) { memset(a,0,LEN); sum = sum_max = 0; for (i = 0;i < n;i++) { scanf("%d",&a[i]); if (sum + a[i] > 0) { sum += a[i]; } else { sum = 0; } if (sum > sum_max) { sum_max = sum; } } printf("%d\n",sum_max); } return 0; }
从而,我们对于1163问题的解答代码如下:
/*********************************************************************** Copyright (c) 2015,wangzp All rights no reserved. Name: 《The Triangle》In PEKING UNIVERSITY ACM ID: PROBLEM 1163 问题简述: 动态规划(DP)很典型的一道题。 动态规划其实就是递推,比递归复杂但是节省时间。 问题算法: 从最后一行开始,往上递推,根据元素大小动态采取存左边的数还是右边的数 把加和的数保存到倒数第二行相对应的数字位置,然后再从倒数第二行开始进行计算 计算到第二行时,把大的值保存在顶部位置,输入最后顶部元素的值即为结果。 Date: Aug 07, 2015 ***********************************************************************/ #include #define LEN 101 int main(void) { int a[LEN][LEN]; int n,i,j; scanf("%d",&n); for (i = 0;i < n;i++) { for (j = 0; j <= i;j++) { scanf("%d",&a[i][j]); } } for (i = n - 2;i >= 0;i--) { for (j = 0;j <= i;j++) { a[i][j] += (a[i+1][j] > a[i+1][j+1] ? a[i+1][j] : a[i+1][j+1]); } } printf("%d\n",a[0][0]); return 0; }