关于这个题目,我初次看来,都已经忘了要怎么做动态规划的题目了,后来一次偶然,看了一下关于动态规划最基础的部分,然后就有了相应地思绪了。
后面花费了我好长的时间去修复一些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();
}
}
这道题目后面想来,其实是动态规划很基础的题目了,如果不懂的话,可以尝试去看看最基本的简单背包问题,之后也能够慢慢理解了。