试题 算法提高 天天向上(画二维数组分析+Java语言实现)

100分

资源限制
时间限制:1.0s   内存限制:256.0MB
问题描述
  A同学的学习成绩十分不稳定,于是老师对他说:“只要你连续4天成绩有进步,那我就奖励给你一朵小红花。”可是这对于A同学太困难了。于是,老师对他放宽了要求:“只要你有4天成绩是递增的,我就奖励你一朵小红花。”即只要对于第i、j、k、l四天,满足i<j<k<l并且对于成绩wi<wj<wk<wl,那么就可以得到一朵小红花的奖励。现让你求出,A同学可以得到多少朵小红花。
输入格式
  第一行一个整数n,表示总共有n天。第二行n个数,表示每天的成绩wi。
输出格式
  一个数,表示总共可以得到多少朵小红花。
样例输入
6
1 3 2 3 4 5
样例输出
6
数据规模和约定
  对于40%的数据,n<=50;
  对于100%的数据,n<=2000,0<=wi<=10000000000。

扩展
例如数字三角形问题,如果使用递归方法实现,对于一个N行的三角形,程序的复杂度会达到O( 2 ^N ),当N为100时,2^N是一个非常大的数字,没有计算机可以在有身之年用那样的递归程序算出结果来。
其实将一个问题分解为子问题递归求解,并且将中间结果保存以避免重复计算的办法,本身就可以被称为“动态规划”。这样对于数字三角形问题,程序的复杂度就变成了O(N^2)。
但是正如大家比较常见的动态规划往往是使用一个一维或者二维数组从下往上递推,确实不需要使用递归,逐行或者逐列递推就可以得到问题的最终解。
这种题需要使用动态规划,用动态规划解题,首先要把原问题分解为若干子问题,这一点和递归方法类似。
如何做动态规划?
1、问题是否具有重叠子问题、具有子结构性质、无后效性?
什么叫具有重叠子问题:不同的问题,可能都要求1个相同问题的解。
比如本题我想知道从第四个数开始,有多少递增序列长度为3,那就需要知道从第五个数开始有多少递增序列为2,知道从第二个数开始,有多少个递增序列为3,也需要知道从第五个数开始有多少个递增序列为2,如下图:
在这里插入图片描述

什么叫具有子结构性质:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最有子结构性质。
什么叫无后效性:当前的若干状态值一旦确定,则此后过程的演变就只和这若干状态的值有关,与之前是采取哪种手段或经过哪条路径演变到当前的若干个状态无关。
2、然后再分析子问题与父问题的关系,以及初始状态、最小子问题。
对于本题:
子问题:就是dp[i][j]的含义(从第i个数开始,所有递增序列的长度为j的和)
父问题:就是dp[i][4]的和,
初始状态:dp[i][j]全为0,
最小子问题:dp[i][1]全为1。


import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner reader=new Scanner(System.in);
		int n=reader.nextInt();
		long[] arr=new long[n];
		long[][] dp=new long[n][5];//不用0列
		for(int i=0;i<n;i++) {
			arr[i]=reader.nextLong();
		}
		for(int i=n-1;i>=0;i--) {
			dp[i][1]=1;
			for(int j=2;j<=4;j++) {
				for(int k=i+1;k<n;k++) {
					if(arr[k]>arr[i]) {
						dp[i][j]+=dp[k][j-1];
					}
				}
			}
		}
		long ans=0;
		for(int i=0;i<n;i++) {
			ans+=dp[i][4];
		}
		System.out.println(ans);
		
	}

}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值