状态转移就是从上一个平台到下一个平台有两种方法,从左端点到下一个平台和从右端点到下一个平台,dp[0][i]表示到第i个平台左端点最小时间,dp[1][i]表示到第i个平台右端点最小时间。
求dp也可以正向求和反向求
import java.util.Arrays;
import java.util.Scanner;
public class Main_POJ1661 {
static node1661[] node = new node1661[1005];
static int[][] dp = new int[2][1005];
static int n,max;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t-- > 0) {
n = sc.nextInt();
int x = sc.nextInt();
int y = sc.nextInt();
max = sc.nextInt();
Arrays.fill(node, null);
node[0] = new node1661(x,x,y);
for(int i=1;i<=n;i++) {
node[i] = new node1661(sc.nextInt(),sc.nextInt(),sc.nextInt());
}
node[n+1] = new node1661(-20005,20005,0);
Arrays.sort(node,0,2+n);
for(int i=0;i<2;i++) {
Arrays.fill(dp[i], 99999999);
}
dp[1][0] = dp[0][0] = 0;
int ans = Integer.MAX_VALUE;
for(int i=0;i<=n;i++) { //正向dp
boolean lf = true,rf = true;
for(int j=i+1;j<=n+1;j++) {
if(!lf&&!rf) break;
if(node[i].h-node[j].h<=max) {
if(lf&&node[i].x1>=node[j].x1&&node[i].x1<=node[j].x2) { //从左端点到下一个平台
lf = false;
if(j==n+1) {
ans = Math.min(ans,dp[0][i]+node[i].h);
}else {
dp[0][j] = Math.min(dp[0][j], node[i].h-node[j].h+dp[0][i]+node[i].x1-node[j].x1);
dp[1][j] = Math.min(dp[1][j], node[i].h-node[j].h+dp[0][i]+node[j].x2-node[i].x1);
}
}
if(rf&&node[i].x2>=node[j].x1&&node[i].x2<=node[j].x2) { //从右端点到下一个平台
rf = false;
if(j==n+1) {
ans = Math.min(ans,dp[1][i]+node[i].h);
}else {
dp[0][j] = Math.min(dp[0][j], node[i].h-node[j].h+dp[1][i]+node[i].x2-node[j].x1);
dp[1][j] = Math.min(dp[1][j], node[i].h-node[j].h+dp[1][i]+node[j].x2-node[i].x2);
}
}
}else break;
}
}
// for(int i=n;i>=0;i--) { 反向dp
// left(i);
// right(i);
// }
// System.out.println(Math.min(dp[0][0], dp[1][0]));
System.out.println(ans);
}
}
// public static void left(int i) {
// int k=i+1;
// while(k<=n&&(node[i].h-node[k].h)<=max) {
// if(node[i].x1>=node[k].x1&&node[i].x1<=node[k].x2) {
// dp[0][i] = node[i].h-node[k].h+Math.min(dp[0][k]+node[i].x1-node[k].x1,dp[1][k]+node[k].x2-node[i].x1);
// return;
// }
// k++;
// }
// if((node[i].h-node[k].h)>max) {
// dp[0][i] = 99999999;
// }else {
// dp[0][i] = node[i].h;
// }
// }
// public static void right(int i) {
// int k=i+1;
// while(k<=n&&(node[i].h-node[k].h)<=max) {
// if(node[i].x2>=node[k].x1&&node[i].x2<=node[k].x2) {
// dp[1][i] = node[i].h-node[k].h+Math.min(dp[0][k]+node[i].x2-node[k].x1,dp[1][k]+node[k].x2-node[i].x2);
// return;
// }
// k++;
// }
// if((node[i].h-node[k].h)>max) {
// dp[1][i] = 99999999;
// }else {
// dp[1][i] = node[i].h;
// }
// }
}
class node1661 implements Comparable<node1661>{
int x1,x2,h;
public node1661(int x1,int x2,int h) {
this.x1 = x1;
this.x2 = x2;
this.h = h;
}
@Override
public int compareTo(node1661 o) {
// TODO Auto-generated method stub
return o.h-this.h;
}
}