有名的数塔问题,对于刚接触DP的同学,应该就是这题吧,这里说一下我的想法和官方的代码。
这题肯定是不可以用最原始的递归的,对于初学DP的同学,可能会用到DP的递归调用,那只是第一步,接着你会把递归的化成非递归的,然后你可能还会想到从下往上计算而不是从上往下计算,因为当你用从上往下计算时,要考虑数组是否越界(也就是没行的第一个,这个数的左上没有数,还有就是每一行的最后一个数,它的右上没有数,这个可以不考虑,数组已经开出来了,不过得初始化为0)。从下往上就不用考虑这么多了。其实考虑到这,基本也差不多了,但是似乎我们得开一个二维数组来存这些结果,可是对于这些结果我们用不着都存起来,当我们考虑到第i行时,我们只要考虑第i-1行就行了,第i-1行以前的所有结果我们都没必要存起来。那么我们就可以用两个一维数组存起来了一个是当前行的最优结果(也就是要算的),还有一个是上一行的最优结果。另外在
01背包里面会用到这样的优化,有时不优化就会MLE。(代码建议自己想先,再参考)
贴一下从下往上算的:
CODE
1/**//*
2 ID:qcx97811
3 LANG:C
4 PROG:numtri
5 */
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9int num[1002][1002];
10int dp[1002][1002];
11int max_int(int a,int b)
12{
13 return a > b ? a:b;
14}
15int main(main)
16{
17 freopen("numtri.in","r",stdin);
18 freopen("numtri.out","w",stdout);
19 int r;
20 int i,j;
21 scanf("%d",&r);
22 for(i = 0;i < r;i++)
23 {
24 for(j = 0;j <= i;j++)
25 scanf("%d",&num[i][j]);
26 }
27 memset(dp,0,sizeof(dp));
28 for(i = 0;i < r;i++)
29 dp[r-1][i] = num[r-1][i];//初始化最后一行的最优解
30 for(i = r-2;i >= 0;i--)
31 {
32 for(j = 0;j <= i;j++)
33 {
34 dp[i][j] = num[i][j] + max_int(dp[i+1][j],dp[i+1][j+1]);//每一行的最优解由它的左下和右下两个得到
35 }
36 }
37 printf("%d\n",dp[0][0]);//最终结果存在第一个元素中,也就是最上面的那个
38 return 0;
39}
40
下面的代码是官方给的(省内存)
CODE2
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <assert.h>
5
6#define MAXR 1000
7
8int
9max(int a, int b)
10{
11 return a > b ? a : b;
12}
13
14void
15main(void)
16{
17 int best[MAXR], oldbest[MAXR];//best是当前行的最优值,oldbest
18//数组是当前行的上一行的最优值
19 int i, j, r, n, m;
20 FILE *fin, *fout;
21
22 fin = fopen("numtri.in", "r");
23 assert(fin != NULL);
24 fout = fopen("numtri.out", "w");
25 assert(fout != NULL);
26
27 fscanf(fin, "%d", &r);
28
29 for(i=0; i<MAXR; i++)
30 best[i] = 0;
31
32 for(i=1; i<=r; i++) {
33 memmove(oldbest, best, sizeof oldbest);//把上一次的最优结果赋值到这次的上一行最优结果中
34 for(j=0; j<i; j++) {
35 fscanf(fin, "%d", &n);
36 if(j == 0)//如果是每行的开头
37 best[j] = oldbest[j] + n;
38 else
39 best[j] = max(oldbest[j], oldbest[j-1]) + n;
40 }
41 }
42
43 m = 0;
44 for(i=0; i<r; i++)//在最后一行查找最优值
45 if(best[i] > m)
46 m = best[i];
47
48 fprintf(fout, "%d\n", m);
49 exit(0);
50}
51