hdu 2084 数塔 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2084

      经典的DP入门题。

      最近学起DP,做回这道题目,用的是自顶向上的方法来求解,发现代码很长,不过时间短了,这应该就是传说中的“以空间换时间”的说法吧。个人觉得,这比较符合人的思考模式,不过真的很繁琐,由于不知道最后一行中最大和的具体位置,还要比较找出。

     状态转移方程是(设f(i, j)为三角形上从点(i,j)出发向下走的最大和路径, a(i, j)表示原始输入的第 i 行第 j 列的数 :

                 f(i, j) = a(i, j) + max{f(i-1, j-1), f(i-1, j)}      i != j  (每行里除第一和最后的处于中间位置的数

                            a(i, j)+ f(i-1, j)                               j = 0   (每行里的第一个数)

                            a(i, j) + f(i-1, j-1)                             j = i   (每行里的最后一个数)

                           

    

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int c, i, j, n, a[105][105], maxsum;
 7     while (scanf("%d", &c) != EOF)
 8     {
 9         while (c--)
10         {
11             scanf("%d", &n);
12             for (i = 0; i < n; i++)
13             {
14                 for (j = 0; j <= i; j++)
15                     scanf("%d", &a[i][j]);
16             }
17             for (i = 1; i < n; i++)
18             {
19                 for (j = 0; j <= i; j++)
20                 {
21                     if (j == 0)    //每行的第一个数只能从它的正上一行+当前行的数
22                     {
23                         a[i][j] = a[i-1][j] + a[i][j];
24                     }
25                     else if (i == j) //每行的最后一个数只能从它的左上一行+当前行的数
26                         a[i][j] = a[i-1][j-1] + a[i][j];
27                     else
28                     {
29                         if (a[i-1][j] > a[i-1][j-1])   //上一行的左边的数和上一行正对着的数比较
30                             a[i][j] = a[i-1][j] + a[i][j];
31                         else
32                             a[i][j] = a[i-1][j-1] + a[i][j];
33                     }
34                 }
35             }
36             maxsum = -100;
37             for (j = 0; j <= n-1; j++)
38                 if (maxsum < a[n-1][j])
39                     maxsum = a[n-1][j];
40             printf("%d\n", maxsum);    
41         }
42     }
43     return 0;
44 }

 

     自底向上的求法:

     (连特殊位置的判断都不用考虑了,而且保证最后输出的a[0][0]一定是最大的)

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int c, i, j, n, a[105][105];
 7     while (scanf("%d", &c) != EOF)
 8     {
 9         while (c--)
10         {
11             scanf("%d", &n);
12             for (i = 0; i < n; i++)
13             {
14                 for (j = 0; j <= i; j++)
15                     scanf("%d", &a[i][j]);
16             }
17             for (i = n - 2; i >= 0; i--)
18             {
19                 for (j = 0; j <= i; j++)
20                 {
21                     if (a[i+1][j] > a[i+1][j+1])
22                         a[i][j] = a[i+1][j] + a[i][j];
23                     else
24                         a[i][j] = a[i+1][j+1] + a[i][j];
25                 }
26             }
27             printf("%d\n", a[0][0]);    
28         }
29     }
30     return 0;
31 }

 

   

 

posted @ 2013-05-21 20:14  windysai  阅读(211)  评论(0编辑  收藏  举报