90 2 2 2
30 20 20
60 20 20
输出
80
⭐ 把起点和终点都当作路口,这样方便处理,每一个循环都是 当前红灯 + 路段(当前灯~下一个灯)的时间
import java.util.*;
public class Main
{
static int n, m, k, v;
static int[] a, b, c;
static long ans = Long.MAX_VALUE;
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
n = sc.nextInt();// 总距离
m = sc.nextInt();// 红绿灯数量
k = sc.nextInt();// 氮气冷却
v = sc.nextInt();// 正常速度
a = new int[m + 2];
b = new int[m + 2];
c = new int[m + 2];
// 输入
for (int i = 1; i <= m; i++)
{
a[i] = sc.nextInt();
b[i] = sc.nextInt();
c[i] = sc.nextInt();
}
a[0] = 0;
b[0] = 1;
c[0] = 0;
a[m + 1] = n;
b[m + 1] = 1;
c[m + 1] = 0;
dfs(0, 0, 0);
System.out.println(ans);
}
// x 表示到第几个红绿灯路口,num表示能不能用氮气,time 表示用时,dist表示已走的距离
private static void dfs(int x, int num, long time)
{
if (x == m + 1)
{
ans = Math.min(ans, time);
// System.out.println(ans);
return;
}
if(time >= ans)
return;
// 判断是否要等红灯
long flag = time % (b[x] + c[x]);
if (flag >= b[x])// 红灯,等待;绿灯,不处理
{
time += (b[x] + c[x] - flag);
}
long t = (long)a[x + 1] * v;
if (x != 0)
t = (long)(a[x + 1] - a[x]) * v;
// System.out.println(t);
if (num == 0)// 能用氮气
{
dfs(x + 1, (num + 1) % k, time);// 用氮气时间不变
dfs(x + 1, num, time + t);// 有,但不用
} else
{
dfs(x + 1, (num + 1) % k, time + t);
}
}
}
⭐ 大佬题解
import java.io.*;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.IntUnaryOperator;
import java.util.stream.IntStream;
public class Main {
static Scanner sc = new Scanner(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static int nextInt() throws Exception {
cin.nextToken();
return (int) cin.nval;
}
// public static long nextLong() throws Exception {
// cin.nextToken();
// return (long) cin.nval;
// }
public static double nextDouble() throws Exception {
cin.nextToken();
return cin.nval;
}
public static String next() throws Exception {
cin.nextToken();
return cin.sval;
}
public static void main(String[] args) throws Exception {
int n = nextInt(), m = nextInt(), k = nextInt(), v = nextInt();
long[][] d = new long[m + 2][3];
//f[i][k - 1] = f[i - 1][0] + c1
//f[i][j] = f[i - 1][j + 1] + c2
//f[i][0] = f[i - 1][0] or f[i - 1][1] => + c3
long[][] f = new long[m + 2][k];
for (int i = 1; i <= m; i++) {
d[i][0] = nextInt();
d[i][1] = nextInt();
d[i][2] = nextInt();
}
for (int i = 0; i < f.length; i++) {
Arrays.fill(f[i], Long.MAX_VALUE);
}
d[m + 1][0] = n;
d[m + 1][1] = 1;
f[0][0] = 0;
for (int i = 1; i <= m + 1; i++) {
if (f[i - 1][0] != Long.MAX_VALUE) {
f[i][k - 1] = f[i - 1][0];
long dt;
long at = d[i][1] + d[i][2];
if ((dt = f[i][k - 1] % at) >= d[i][1]) {
f[i][k - 1] += at - dt;
}
}
long tmp;
if ((tmp = Math.min(f[i - 1][0], f[i - 1][1])) != Long.MAX_VALUE) {
f[i][0] = v * (d[i][0] - d[i - 1][0]) + tmp;
long dt;
long at = d[i][1] + d[i][2];
if ((dt = f[i][0] % at) >= d[i][1]) {
f[i][0] += at - dt;
}
}
for (int j = 1; j < k - 1; j++) {
if (f[i - 1][j + 1] != Long.MAX_VALUE) {
f[i][j] = v * (d[i][0] - d[i - 1][0]) + f[i - 1][j + 1];
long dt;
long at = d[i][1] + d[i][2];
if ((dt = f[i][j] % at) >= d[i][1]) {
f[i][j] += at - dt;
}
}
}
}
System.out.println(Arrays.stream(f[m + 1]).min().getAsLong());
}
}