蓝桥杯试题 算法提高 第二点五个不高兴的小明 Java

关于这个题目,我初次看来,都已经忘了要怎么做动态规划的题目了,后来一次偶然,看了一下关于动态规划最基础的部分,然后就有了相应地思绪了。
后面花费了我好长的时间去修复一些bug,我把原题贴在下面:

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  有一条长为n的走廊,小明站在走廊的一端,每次可以跳过不超过p格,每格都有一个权值wi。
  小明要从一端跳到另一端,不能回跳,正好跳t次,请问他跳过的方格的权值和最大是多少?
输入格式
  输入的第一行包含两个整数n, p, t,表示走廊的长度,小明每次跳跃的最长距离和小明跳的次数。
  接下来n个整数,表示走廊每个位置的权值。
输出格式
  输出一个整数。表示小明跳过的方格的权值和的最大值。
样例输入
8 5 3
3 4 -1 -100 1 8 7 6
样例输出
12
数据规模和约定
  1<=n, p, t<=1000, -1000<=wi<=1000。

注意这个题目也是有坑的,比如它的两端,其实定义在所有的权值的外面。最初的时候我以为初始端是最前面的一个格子的值,然后就疯狂出错了。
基本原理就是一步一步的跳,然后分析每一步到达的最近距离到最远距离,在每个距离中获取前一跳中能够得到的最大权值,做相应地保存。最后输出最大的权值。
下面我把自己写的源码贴在下面,解释也相应地放在里面了:

import java.util.*;
import java.io.*;

public class Main
{
	public static void main(String args[]) throws IOException
	{
		StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		//输入数据
		in.nextToken();
		int n = (int)in.nval;
		in.nextToken();
		int p = (int)in.nval;
		in.nextToken();
		int t = (int)in.nval;
		int[] m = new int[1010];
		for(int i = 1; i <= n; i++)
		{
			in.nextToken();
			m[i] = (int)in.nval;
		}
		//处理数据
		int[][] v = new int[1010][1010];
		//一步一步地跳
		for(int i = 1; i <= t; i++)
		{
			//每一步到达每个格子的处理
			//因为每次跳至少要一个格子,所以j = i代表到达第j个格子最多跳跃了i次
			//j <= n + 1代表走廊的长度+1,加一用于求取最后的值
			//j <= p * i代表每次跳跃最远为p格,j次跳跃最远为p * i
			for(int j = i; j <= n + 1 && j <= p * i; j++)
			{
				//从第j - p个格子算起(因为最远是这个格子才能到达j点),然后i - 1代表前面最少跳跃了i - 1次,然后能到达的格子至少是i - 1
				int k = Math.max(j - p, i - 1);
				//获取一个合理值
				v[i][j] = m[j] + v[i - 1][k];
				//获取最大值(包含自身点)
				//k < j代表j格子的前一个格子,k <= p * (i - 1)代表前面的i - 1次跳跃最远到达的距离为p * (i - 1)
				for(k++ ;k < j && k <= p * (i - 1); k++)
				{
					v[i][j] = Math.max(v[i - 1][k] + m[j], v[i][j]);
				}
			}
		}
		//输出第t次跳跃后到达走廊另一端(n + 1)时的最大值
		out.println(v[t][n + 1]);
		
		out.flush();
	}
}

这道题目后面想来,其实是动态规划很基础的题目了,如果不懂的话,可以尝试去看看最基本的简单背包问题,之后也能够慢慢理解了。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值