Lucifer's Pyramid of Numbers

Lucifer's Pyramid of Numbers

 

时间限制:1000ms        内存限制:65535kB

描述

    Lucifer has a strange hobby, he sometimes put offending evils to the Pyramid of Numbers (PoN), and then decides whether he will liberate the evils or not through a game.

    In PoN, the poor evil could only move straightly down or bottom-right step by step. An evil, the sum of numbers on whose moving path is the biggest one among all probable sums, will be liberated and otherwise it will be killed.

    Aiushtha (EH, Enchant, 魅惑魔女) has been arrested by Lucifer because she always say “I’m game!” in DotA but Lucifer took the pet phrase as “I’m gay!”. What’s more, Lucifer improves the degree of difficulty since EH is smart. He gives EH a once only tool and in a particular step, EH could move to any point in the nether adjacent level she wants by one step.

    Your task is to calculate the biggest number that Aiushtha can get.

输入
THERE ARE MULTIPLE TESTCASES.
The first line of each testcase is a number N(0<=N<=1000).
The following N lines describes the PoN as the Sample Input. Each number appeared is in the range from -1000 to 1000. (-1000<=number<=1000)
输出
answer
样例输入
5                   
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
样例输出
35

分析:

大致题意:有个数字三角形,从上而下,每次只能连接自己下一层所对着的元素,或所对着的元素右边的元素。

 这样从上而下,每层按这个方法取一个元素,使和最大。这前面的叙述其实就是下面这个网址题的题意,该题不同的是,你有一次机会可跳到下一层任何一个位置, 当然包括有连接的位置。

做道题之前,可以先看一下更简单的甲题http://www.cnblogs.com/jiangjun/archive/2012/08/11/2634134.html

由甲题第二种方法,看起来似乎就是本道题的方法;但仔细一想本题确实要比甲题难多了
思路:既然本题不止要存回溯值,还要存出现最大值更新的新表,那就将dp[N][N]改成dp[N][N][2];

         当然还要用一个一维数组存每排的最大值,问题就在会不会跳多次?

         这就要求这个一维数组要根据回溯后表的更新,不断更新自己的值;那即使再次取该最大值,也是按甲题的规则得到的,也就相当于前面的更新无效,也只算这一次

还是看如下代码吧:

# include<stdio.h>
# include<string.h>
#define inf 1<<30
#define N 1005
int n, dp[N][N][2];
int num[N];
int tmax(int a,int b)
{
    return a>b?a:b;
}
void Dp()
{
    int i, j;
    for (i = n - 1; i >= 1; i--)
    {
        for (j = 1; j <= i; j++)
        {
            dp[i][j][1] += tmax(num[i+1], tmax(dp[i+1][j+1][1], dp[i+1][j][1]));
            //这里相当于将子节点的值返回,再和子排正常得到的最大值num[i+1]取较大的一个
            //不管num[i+1]被取了多少次,都是取自 dp[i][j][0],即它是按甲题原规则,没跳过取的
            dp[i][j][0] += tmax(dp[i+1][j][0], dp[i+1][j+1][0]);//回溯叠加        
            num[i] = tmax(num[i], dp[i][j][0]);//不断更新得到每排新的最大值
        }
    }
    printf("%d\n", dp[1][1][1]);
}
int main()
{
    int temp, i, j;
    while (scanf("%d", &n) != EOF)
    {
        for (i = 1; i <= n; i++)
        {
            temp = -inf;
            for (j = 1; j <= i; j++)
            {
                scanf("%d", &dp[i][j][0]);
                dp[i][j][1] = dp[i][j][0];
                if(dp[i][j][0] > temp)
                    temp = dp[i][j][0];
            }
            num[i] = temp;//获得每排的最大值
        }
        Dp();
    }
    return 0;
}

 

 

posted on 2012-10-30 21:10  即为将军  阅读(273)  评论(0)    收藏  举报

导航