POJ1163(简单的DP)

时间:2021-03-06 15:13:08

题目链接:http://poj.org/problem?id=1163

Description

7
3 8
8 1 0
2 7 4 4
4 5 2 6 5 (Figure 1)

Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right.

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
题意:在上面的数字三角形中寻找一条从顶部到底边的路径,使得 路径上所经过的数字之和最大。路径上的每一步都只能往左下或 右下走。只需要求出这个最大和即可,不必给出具体路径。三角形的行数大于1小于等于100,数字为 0 - 99
解题思路:我们可以用二维数组存放数字三角形。map( i, j)   : 第i行第 j 个数字(i,j从1开始算).它是一个典型的递归问题。 map(i, j)出发,下一步只能走map(i+1,j)或者map(i+1, j+1)。但是如果采用递规的方法,深度遍历每条路径,存在大 量重复计算。则时间复杂度为 2^n,对于 n = 100 行,肯定超时。这里我们可以采用两种方法,第一种是采用记忆搜索的方法,如果每算出一个数组就保存起来,下次用 到其值的时候直接取用,则可免去重复计算。第二种是我们可以从下往上看,因为从顶边到底边的路径是和从底边到顶边的路径是一样的。我们把从第n行到第i行第j列位置的最大数字和设为dp[i][j],它肯定是底层到第i+1行的第j列的数字和即dp[i+1][j]或者到第i+1行第j+1列的数字和即dp[i+1][j+1]加上一个map[i][j]得得到的,根据动态规划的思想,我们应该去两者中更大的那个解即最优解,于是我们就能得到递推公式(即状态转移方程):dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+map[i][j],这样我们通过从最底层一步一步向上递推就很简单了,而我们要求的答案也正是最顶层的最优解即dp[1][1].
初学DP,如有不正确的地方,望指正,谢谢。
附上代码:
 #include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
int n;
int map[][];
int dp[][]; int main()
{
cin>>n;
for(int i=;i<=n;i++){
for(int j=;j<=i;j++){
cin>>map[i][j];
}
}
memset(dp,,sizeof(dp));
for(int i=n;i>;i--)
{
for(int j=;j<=i;j++)
{
dp[i][j]=max(dp[i+][j],dp[i+][j+])+map[i][j];
}
}
cout<<dp[][]<<endl;
return ;
}