http://poj.org/problem?id=1661
题意:一个人从(x,y)开始往下跳, 最高一次往下跳max, 中间有n个板子, 板子有左右端点位置和高度, 问最短多远到地面上.
思路:
考虑最短路
起点0, 每个板子左右端点共2*n个点, 地面设为2*n+1
建边:
起点能到的有两种情况: 1 第一个板子的左端点和右端点
2 直接落到地上
中间的点能到的情况: 1 对于每个点(的左右端点)搜索下面能到的第一个板子(的左右端点)
2 如果高度差超过max, 这个点的出边就建完了
3 如果下面找不到板子, 看是否能落地
跑dijstra
代码:
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef long long ll;
const int M=2e5+5;
const int inf=1e9+5;
const int mod=1e9+7;
//memset(a,0x3f,sizeof(a));
int n,x,y,_max;
int s,e;
struct node {//板子
int x1,x2,h;
} a[1005];
bool cmp(node a,node b) {
return a.h>b.h;
}
struct node2 {//边
int v,w;
int nxt;
} edge[4005];
int head[2005];
int d[2005];
int ei;
void addedge(int u,int v,int w) {
edge[ei].v=v,edge[ei].w=w;
edge[ei].nxt=head[u];
head[u]=ei++;
}
struct HeapNode {
ll d, u;
bool operator < (const HeapNode& rhs)const {
return d>rhs.d;
}
};
priority_queue<HeapNode>Q;
bool done[12005] = { 0 };
void dj() {
for (int i = 0; i <=2*n+1; i++)
d[i] = inf;
d[s] = 0;
Q.push(HeapNode{ 0,s });
while (!Q.empty()) {
HeapNode x = Q.top();
Q.pop();
int u = x.u;
if (done[u])
continue;
done[u] = 1;
for (int i = head[u]; i != -1; i = edge[i].nxt) {
node2&e = edge[i];
if (d[e.v]>d[u] + e.w) {
d[e.v] = d[u] + e.w;
Q.push(HeapNode{ d[e.v],e.v });
}
}
}
}
void Addedge() {
s=0,e=2*n+1;
int f3=0;//起点下有无板子
for(int i=1; i<=n; i++) {
if(a[i].x1<=x&&x<=a[i].x2) {
f3=1;
addedge(s,i,x-a[i].x1);//1->n表示所有板子的左端点
addedge(s,i+n,a[i].x2-x);//1+n->n+n表示所有板子的右端点
break;
}
}
if(f3==0)
addedge(0,2*n+1,0);
for(int i=1; i<=n; i++) {
int f1=0,f2=0;//这个板子的左端点/右端点下方有没有板子接着
for(int j=i+1; j<=n; j++) {
if(a[j].h==a[i].h)
continue;
if(a[i].h-a[j].h>_max)
break;
int l=a[i].x1,r=a[i].x2;
if(l>=a[j].x1&&l<=a[j].x2&&!f1) {
f1=1;
addedge(i,j,l-a[j].x1);
addedge(i,j+n,a[j].x2-l);
}
if(r>=a[j].x1&&r<=a[j].x2&&!f2) {
f2=1;
addedge(i+n,j,r-a[j].x1);
addedge(i+n,j+n,a[j].x2-r);
}
}
if(f1==0) {
if(a[i].h<=_max) {
addedge(i,e,0);
}
}
if(f2==0) {
if(a[i].h<=_max) {
addedge(i+n,e,0);
}
}
}
}
void init(){
ei=0;
memset(done, 0, sizeof(done));
memset(head, -1, sizeof(head));
while (!Q.empty())
Q.pop();
}
int main() {
int _;
scanf("%d",&_);
while(_--) {
init();
scanf("%d%d%d%d",&n,&x,&y,&_max);
for(int i=1; i<=n; i++) {
scanf("%d%d%d",&a[i].x1,&a[i].x2,&a[i].h);
}
sort(a+1,a+n+1,cmp);
Addedge();
dj(); //垂直高度其实与如何走是无关的,永远是y
printf("%d\n",d[e]+y);//所以dj时只算水平距离的最短路即可
}
return 0;
}