刚看到这道题的时候小小的兴奋了一下,竟然是道poj中少见的中文题,所以这里就不多介绍题意了(反正写了也没人看)。
看到题后有两种思路,dp和有向图的最短路,按理说应该都可以写出来。
本蒟蒻认为dp还是比较简单的。f(i,j)表示在第j个平台从i方向掉落到地的最短时间,写之前按高度从小到大排序,
转移的时候找到两个方向底下的平台,f(i,j)就等于min(f(1,x)+两点横坐标之差+△h1,f(2,x)+ 两点横坐标之差(要考虑下左右方向)+△h1)。
下边是代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define mx 1000000
using namespace std;
int t;
int f[3][1010];
int n,x,y,maxx;
struct node
{
int x1,x2,h;
}a[1010];
bool operator < (node c,node b)
{
return c.h<b.h;
}
int main()
{
cin>>t;
for(int i=1;i<=t;i++)
{
memset(f,mx,sizeof(f));
cin>>n>>x>>y>>maxx;
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);
f[1][1]=f[2][1]=a[1].h;
for(int i=2;i<=n;i++)
{
int dis=0;
for(int j=i-1;j>=1;j--)
{
if(a[i].h-a[j].h>maxx)
{
dis=1;
break;
}
if(a[i].x1<=a[j].x2&&a[i].x1>=a[j].x1)
{
f[1][i]=min(f[1][j]+a[i].x1-a[j].x1,f[2][j]+a[j].x2-a[i].x1)+a[i].h-a[j].h;
if(f[1][i]>mx)f[1][i]=mx;
dis=1;
break;
}
}
if(dis==0&&a[i].h<=maxx)
{
f[1][i]=a[i].h;
}
dis=0;
for(int j=i-1;j>=1;j--)
{
if(a[i].h-a[j].h>maxx)
{
dis=1;
break;
}
if(a[i].x2<=a[j].x2&&a[i].x2>=a[j].x1)
{
f[2][i]=min(f[1][j]+a[i].x2-a[j].x1,f[2][j]+a[j].x2-a[i].x2)+a[i].h-a[j].h;
if(f[2][i]>mx)f[2][i]=mx;
dis=1;
break;
}
}
if(dis==0&&a[i].h<=maxx)
{
f[2][i]=a[i].h;
}
}
for(int i=n;i>=1;i--)
{
if(a[i].x1<=x&&a[i].x2>=x)
{
cout<<(min(f[1][i]+x-a[i].x1,f[2][i]+a[i].x2-x)+(y-a[i].h))<<endl;
break;
}
if(i==1)cout<<y<<endl;//考虑到直接掉到地上。
}
}
return 0;
}