DP 初学者必做经典题目 数塔

题目的方法我不过多叙述,可以去 网上搜一下DP的讲义,我这里用了两种方法来做,都是用二元组去描述状态的。代码直接可以运行,是第二种方法,直接求顶层的元素到底层每个元素的最大和值,去掉第二种,就是第一种,我已经注释表明,是求从顶层到下面每层没个数字的最大和值。题目很好,典型的DP思想
 
 
//数塔//
//题目链接:http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?cid=4493&pid=1001&ojid=1
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[200][200];
int high;
int temp[200][200]; 
int result[200];
/*   NO.1
int f(int a,int b)                 //求第a行第b个元素到底部的最大和值//
{
	if(a==high)
	{
		dp[a][b]=temp[a][b];
		return dp[a][b];
	}
	if(dp[a][b]!=-1) return dp[a][b];
	dp[a][b]=temp[a][b]+max(f(a+1,b),f(a+1,b+1));
	return dp[a][b];
}
*/
//NO .2//
int f(int a,int b)            //求解顶层到第a层第b个元素的最大和值//
{
	if(a==1) return temp[1][1];
	if(dp[a][b]!=-1) return dp[a][b];        //记忆化剪枝//
	dp[a][b]=temp[a][b]+max(f(a-1,b-1),f(a-1,b));
	return dp[a][b];
}
int cmp(int x,int y)
{
	return x>y;
}
int main()
{
	int i,j,k;
	int cas;
	while(scanf("%d",&cas)!=EOF)
	{
		while(cas--)
		{
		scanf("%d",&high);
		memset(dp,0xff,sizeof(dp));
		dp[1][1]=1;
		for(i=1;i<=high;i++)
			for(j=1;j<=i;j++)
				scanf("%d",&temp[i][j]);
		/*  NO.1
		      printf("%d\n",f(1,1));
		*/

		//NO.2//
		for(i=1;i<=high;i++)
			result[i]=f(high,i);
		sort(result+1,result+high+1,cmp);
		printf("%d\n",result[1]);
		//NO.2//
		}
	}
	return 0;
}

你可能感兴趣的:(DP 初学者必做经典题目 数塔)