题目大意:POJ少有的中文题,自己看吧,题意挺简单的。
思路:这本是一道DP的题,被我用最短路水过去了,没想到还0ms。
建图的思路比较简单,就是实现起来比较费劲。把每个东西按高度排序,从上到下n^2的枚举左右端点,然后满足条件的连边,边权为高度差+水平距离差。
然后跑SPFA就行了。注意一下Jimmy直接能跳到地面上的情况,这wa了一次。
CODE:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 200010
using namespace std;
struct Complex{
int l,r;
bool _l,_r;
int height;
Complex(int _,int __,int ___):l(_),r(__),height(___) {}
Complex() {}
bool operator <(const Complex &a)const {
return height > a.height;
}
void Read() {
scanf("%d%d%d",&l,&r,&height);
_l = _r = false;
}
}point[MAX];
int cases;
int points,x,y,limit;
int head[MAX],total;
int next[MAX],aim[MAX],length[MAX];
int f[MAX];
bool v[MAX];
inline void Initialize();
inline void Add(int x,int y,int len);
inline void SPFA(int start);
int main()
{
for(cin >> cases;cases; --cases) {
scanf("%d%d%d%d",&points,&x,&y,&limit);
Initialize();
for(int i = 1;i <= points; ++i)
point[i].Read();
point[++points] = Complex(-20000,20000,0);
point[0].height = y;
sort(point + 1,point + points + 1);
for(int i = 1;i <= points; ++i)
if(x >= point[i].l && x <= point[i].r)
if(y - point[i].height <= limit) {
Add(1,i << 1,y - point[i].height + x - point[i].l);
Add(1,i << 1|1,y - point[i].height + point[i].r - x);
break;
}
for(int i = 1;i <= points; ++i)
for(int j = 1;j < i; ++j) {
if(point[j].height - point[i].height > limit) continue;
if(!point[j]._l && point[j].l >= point[i].l && point[j].l <= point[i].r) {
Add(j << 1,i << 1,point[j].height - point[i].height + point[j].l - point[i].l);
Add(j << 1,i << 1|1,point[j].height - point[i].height + point[i].r - point[j].l);
point[j]._l = true;
}
if(!point[j]._r && point[j].r >= point[i].l && point[j].r <= point[i].r) {
Add(j << 1|1,i << 1,point[j].height - point[i].height + point[j].r - point[i].l);
Add(j << 1|1,i << 1|1,point[j].height - point[i].height + point[i].r - point[j].r);
point[j]._r = true;
}
}
SPFA(1);
printf("%d\n",f[points << 1]);
}
return 0;
}
inline void Initialize()
{
total = 0;
memset(head,0,sizeof(head));
}
inline void Add(int x,int y,int len)
{
next[++total] = head[x];
aim[total] = y;
if(y == (points << 1) || y == (points << 1|1))
length[total] = point[x >> 1].height;
else length[total] = len;
head[x] = total;
}
inline void SPFA(int start)
{
static queue<int> q;
while(!q.empty()) q.pop();
memset(f,0x3f,sizeof(f));
f[start] = 0;
q.push(start);
while(!q.empty()) {
int x = q.front(); q.pop();
v[x] = false;
for(int i = head[x];i;i = next[i])
if(f[aim[i]] > f[x] + length[i]) {
f[aim[i]] = f[x] + length[i];
if(!v[aim[i]]) {
v[aim[i]] = true;
q.push(aim[i]);
}
}
}
}