• The Triangle


    题目限制

    Time Limit: 1000MS Memory Limit: 10000K
    Total Submissions: 59262 Accepted: 35557
    时间限制: 1000ms 内存限制: 10000k
    提交:59262 接受:35557

    Description

    描述

    			    7
    		   	  3   8
    			8   1   0
    		  2   7   4   4
    		4   5   2   6   5
    

    (Figure 1)
    Figure 1 shows a number triangle.
    图1显示了一个数字三角形。
    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.
    第一行包含一个整数n:三角形中的行数。
    The following N lines describe the data of the triangle.
    下面的n行描述了三角形的数据。
    The number of rows in the triangle is > 1 but <= 100.
    三角形中的行数大于1但小于等于100。
    The numbers in the triangle, all integers, are between 0 and 99.
    三角形中的数字,所有整数,都在0到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
    Source
    IOI 1994

    解题思路

    用二维数组存放数字三角形

    D(i,j):第i行第j个数字(r,j从1开始算)
    MaxSum(r,j):从D(i,j)到底边的各条路径,最佳路径的数字之和。

    问题:求MaxSum(1,1)

    典型的递归问题:
    D(i,j)出发,下一步只能走到D(i+1,j)或者D(i+1,j+1)。

    递归代码

    #include <iostream>
    #include <algorithm>
    #define MAX 101
    using namespace std;
    int D[MAX][MAX];
    int n;
    int MaxSum(int i,int j)
    {
    	if(i==n)
    	{
    		return D[i][j];
    	}
    	int x=MaxSum(i+1,j);
    	int y=MaxSum(i+1,j+1);
    	return max(x,y)+D[i][j];
    }
    int main()
    {
    	int i,j;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    			cin>>D[i][j];
    		}
    	}
    	cout<<MaxSum(1,1)<<endl;
    	return 0;
    }
    

    想都不用想,肯定会:Time Limit Exceeded

    为什么会超时?

    重复计算:
    如果采用递归的方法,深度遍历每条路径,存在大量重复计算,时间复杂度为2n

    改进

    如果每算出一个MaxSum()就保存起来,下次用到其值的时候直接取用,则可免去重复计算。
    因为三角形的数字总数是n(n+1)/2,那么可以用O(n2)时间完成计算。

    记忆递归型动态规划程序

    #include <iostream>
    #include <algorithm>
    #define MAX 101
    using namespace std;
    int maxSum[MAX][MAX];
    int D[MAX][MAX];
    int n;
    int MaxSum(int i,int j)
    {
    	if(maxSum[i][j]!=-1)
    	{
    		return maxSum[i][j];
    	}
    	if(i==n)
    	{
    		maxSum[i][j]=D[i][j];
    	}
    	else
    	{
     	 	int x=MaxSum(i+1,j);
    		int y=MaxSum(i+1,j+1);
    		maxSum[i][j]=max(x,y)+D[i][j];
    	}
    	return maxSum[i][j];
    }
    int main()
    {
    	int i,j;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    			cin>>D[i][j];
    			maxSum[i][j]=-1;
    		}
    	}
    	cout<<MaxSum(1,1)<<endl;
    	return 0;
    }
    

    递归转递推

    从下往上,每两个数往上找一层最大数:
    在这里插入图片描述

    #include <iostream>
    #include <algorithm>
    #define MAX 101
    using namespace std;
    int D[MAX][MAX],n;
    int maxSum[MAX][MAX];
    int main ()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    			cin>>D[i][j];
       			if(i==n) maxSum[n][j]=D[n][j];
    		}
    	}
    	for(int i=n-1;i>=1;i--)
    	{
    		for(int j=1;j<=i;j++)
    		{
    			maxSum[i][j]=max(maxSum[i+1][j],maxSum[i+1][j+1])+D[i][j];
    		}
    	}
    	cout<<maxSum[1][1]<<endl;
    	return 0;
    }
    

    空间优化

    直接用D的最后一行存放maxSum

    #include <iostream>
    #include <algorithm>
    #define MAX 101
    using namespace std;
    int D[MAX][MAX],n;
    int * maxSum;
    int main ()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    			cin>>D[i][j];
    		}
    	}
    	maxSum=D[n];
    	for(int i=n-1;i>=1;i--)
    	{
    		for(int j=1;j<=i;j++)
    		{
    			maxSum[j]=max(maxSum[j],maxSum[j+1])+D[i][j];
    		}
    	}
    	cout<<maxSum[1]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    简练软考知识点整理-四控三管一协调
    软考如何刷题
    简练软考知识点整理-瀑螺原迭敏V
    简练软考知识点整理-外指赶快先提投降
    简练软考知识点整理-实施整体变更控制过程
    简练软考知识点整理-监控项目工作过程
    简练软考知识点整理-指导与管理项目工作过程
    简练软考知识点整理-制定项目管理计划过程
    Day10文件内指针移动和函数
    Day09文件操作
  • 原文地址:https://www.cnblogs.com/AlexKing007/p/12339438.html
Copyright © 2020-2023  润新知