题目链接:http://poj.org/problem?id=1661
联动:http://blog.csdn.net/csdn364988181/article/details/48208349
题意:场景中有n个平台,角色从某个地方下落,到达地面结束,从一个平台到另一个平台不可以超过max,不然摔死,在平台上移动速度是1m/s,下落的速度也是1m/s,问最快到达地面要多少
思路:立刻想到了之前用线段树处理每一个平台左右落点的题目(联动hdu3016的题解),但是这一题数据比较小,直接暴力判断落点就可以了,递推的方式特有些不一样,但大体上思路是一样的,一个平台只能选择左右2个地方下落,按高度进行排序一直递推上去就可以了,[0,10]的平台是可以从右侧落到[10,100]上的逻辑(一开始我没在意,不过有人写的题解抱怨了这个逻辑)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;
struct Node
{
int xl,xr,h;
}s[1030];
int lim,n;
int dp[1030][5];
bool cmp(Node p,Node q)
{
return p.h<q.h;
}
void Leftmintime(int now)
{
int tmp=now-1;
while (tmp>0 && s[now].h-s[tmp].h <= lim)
{
if (s[now].xl >= s[tmp].xl && s[now].xl <= s[tmp].xr)
{
int mintim=min(s[now].xl-s[tmp].xl+dp[tmp][0],s[tmp].xr-s[now].xl+dp[tmp][1]);
dp[now][0]=s[now].h-s[tmp].h+mintim;
return;
}
else tmp--;
}
if (s[now].h > lim)
dp[now][0]=inf;
else
dp[now][0]=s[now].h;
return;
}
void Rightmintime(int now)
{
int tmp=now-1;
while (tmp>0 && s[now].h-s[tmp].h <= lim)
{
if (s[now].xr >= s[tmp].xl && s[now].xr <= s[tmp].xr)
{
int mintim=min(s[now].xr-s[tmp].xl+dp[tmp][0],s[tmp].xr-s[now].xr+dp[tmp][1]);
dp[now][1]=s[now].h-s[tmp].h+mintim;
return;
}
else tmp--;
}
if (s[now].h > lim)
dp[now][1]=inf;
else
dp[now][1]=s[now].h;
return;
}
int solve()
{
for (int i=1;i<=n+1;i++)
{//cout<<":"<<endl;
Leftmintime(i);
Rightmintime(i);
}
int res=min(dp[n+1][0],dp[n+1][1]);
return res;
}
int main()
{
int t,x,y;
scanf("%d",&t);
while (t--)
{
scanf("%d%d%d%d",&n,&x,&y,&lim);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&s[i].xl,&s[i].xr,&s[i].h);
}
s[0].xl=-inf;
s[0].xr=inf;
s[0].h=0;
s[n+1].xl=x;
s[n+1].xr=x;
s[n+1].h=y;
sort(s,s+n+1,cmp);
int res=solve();
printf("%d\n",res);
}
}