Cow Roller Coaster 动态规划 java实现
题目链接:Cow Roller Coaster
开始想着类似于图,根据起点终点连接,然后进行搜索,得出结果,但是没做出来.然后百度了一下,应当使用动态规划来做.
思路
1.使用二维数组DP[L+1][C(max)+1]进行动态规划.dp[i][j]表示搭建到i的距离所用花费为j时候所获得的最大乐趣.
为了容易写转移方程,将输入数据处理一下.
a.设输入为data[][4].输入为s,t,f,c.表示起始位置,长度,乐趣和花费.
data[i][0]表示起始位置s.
data[i][1]表示使用i能够到的最终位置.所以data[i][1]=data[i][0]+t.
data[i][2]表示使用i的乐趣.
data[i][3]表示使用i的花费.
b.将数据data[][]按照起始位置从小到大排序,如果起始位置相同,按照终点位置从小到大排序.
2.写转移方程.
{到达data[i][5]花费为j的最大乐趣}=Max{{到达某长度时的最大乐趣+使用i方式所获得的乐趣},到达data[i][6]花费为j的最大乐趣}.
使用i方式所获得的乐趣为data[i][2],某长度应当是使用i方式的时候的起始长度,应当是data[i][0].
dp[i][j]实际就是dp[data[i][7]][j].data[i][8]表示使用i到达的最终位置.
所以,转移方程为:
dp[data[i][9]][j] = Max{dp[data[i][0]][j-data[i][3]]+data[i][2],dp[data[i][10]][j]},条件为dp[data[i][0]][j-data[i][3]]>=0.(只有经过了某长度后,才能够再使用i方式得到一条路径,所以条件是结果某长度的路径是存在的.)
计算所有dp结果后,从dp[L]中获取最大值即可.
因为如果没有符合条件的,输出-1,所以让dp数组初始化为-1.
完整代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
public class source {
static int L;
static int N;
static int B;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
L = Integer.parseInt(st.nextToken());
N = Integer.parseInt(st.nextToken());
B = Integer.parseInt(st.nextToken());
int[][] data = new int[N+1][4];
for(int i = 1;i<=N;i++){
st = new StringTokenizer(br.readLine());
data[i][0] = Integer.parseInt(st.nextToken());
data[i][1] = Integer.parseInt(st.nextToken())+data[i][0];
data[i][2] = Integer.parseInt(st.nextToken());
data[i][3] = Integer.parseInt(st.nextToken());
}
Arrays.sort(data, new Comparator<int[]>() {
@Override
public int compare(int[] ints, int[] t1) {
if(ints[0] == t1[0]){
return ints[1]-t1[1];
}
return ints[0]-t1[0];
}
});
int[][] dp = new int[1001][1001];
for(int i = 0;i<dp.length;i++){
int[] fill = new int[1001];
Arrays.fill(fill,-1);
dp[i] = fill;
}
dp[0][0] = 0;
for(int i = 1;i<=N;i++){ for(int j = B;j>=data[i][3];j--){
if(dp[data[i][0]][j-data[i][3]]>=0){
dp[data[i][1]][j] = Math.max(dp[data[i][3]][j],dp[data[i][0]][j-data[i][3]]+data[i][2]);
}
}
}
int res = -1;
for(int i = 1;i<=B;i++){
res = Math.max(res,dp[L][i]);
}
System.out.println(res);
}
}
在执行遍历的时候的循环:
for(int i = 1;i<=N;i++){ for(int j = B;j>=data[i][3];j--){
xxxxxxx
}
}
}
因为最终dp[i][j]是到达i的时候的最大花费.
而data[i]中的i表示的是钢轨的编号,所以第一层循环实际上是遍历1~N的编号.
第二层循环是确定j的范围,j是总花费.转移方程中一部分是{到达某长度时的最大乐趣+使用i方式所获得的乐趣},所以j的总花费一定是不小于使用i方式后的花费,而到达某长度的花费有可能是0,所以j>=data[i][3].而花费要求最大值是B,所以j不能大于B.
------关于这个转移方程,也是看到网上说的才知道,自己不容易想出来. ::aru:distressed::

浙公网安备 33010602011771号