POJ 1661

时间:2021-01-06 04:52:32

http://poj.org/problem?id=1661

POJ 1661

这是一道DP的题目,求最优解

上面的这一个题是对于那个重左边开始上的函数的解释

题目要求的是从最高掉下来的小时间,那么我们就可以求从最低处上到最高处的最短时间,反过来

 #include <stdio.h>
#include <stdlib.h> int dp[][],N,max1; struct In{
int h;
int lx;
int rx;
}s[]; int cmp(const void *a,const void *b)
{
return (*(In *)a).h-(*(In *)b).h;
}
int Min1(int x,int y)
{
return (x<y)?x:y;
} void turnleftmintime(int i)
{
int k=i-;
while(k>&&s[i].h-s[k].h<=max1) //由于是从下面往上面走,所以呢,第一层肯定不在地上,因为在地上不需要移动距离,只需要跳上去的时间便可,且上一层一下一层的距离肯定要小于最大距离
{
if(s[i].lx>=s[k].lx&&s[i].lx<=s[k].rx)      //这个就是那个图示的意思了,s[i].lx>=s[k].lx代表着下一层的左边肯定要在上一层左边的左边,意思就是上一层的左边肯定要大于下一层的右边
                                   //且上一层的左边肯定也要在下一层的右边的左边,不然没有交集跳不上,如果上一层不符合的话,那么从下下一层在试,因为上一层肯定是要用到的,
{
dp[i][] = s[i].h-s[k].h+Min1(s[i].lx-s[k].lx+dp[k][],s[k].rx-s[i].lx+dp[k][]); //dp[i][0]是用来存从左边开始往上跳到第i层的最短时间,而其它的时间就是等于距离差加上,从左边上和从右边上的时间,选择时间短的。 return;
}
else k--;
}
if(s[i].h-s[k].h>max1) //这个就是考虑前几层都不符合条件的情况下还有跳第一层时的情况
dp[i][]=;
else dp[i][]=s[i].h;
} void turnrightmintime(int i)
{
int k=i-;
while(k>&&s[i].h-s[k].h<=max1)
{
if(s[i].rx<=s[k].rx&&s[i].rx>=s[k].lx)
{
dp[i][]=s[i].h-s[k].h+Min1(s[i].rx-s[k].lx+dp[k][],s[k].rx-s[i].rx+dp[k][]);
return;
}
else k--;
}
if(s[i].h-s[k].h>max1)
dp[i][]=;
else dp[i][]=s[i].h;
} int shorttime()
{
int i;
for(i=;i<=N+;i++)
{
turnleftmintime(i);
turnrightmintime(i);
}
return Min1(dp[N+][],dp[N+][]);
} int main()
{
int n,x,y;
scanf("%d",&n);
while(n)
{
n--;
scanf("%d%d%d%d",&N,&x,&y,&max1);
for(int i=;i<=N;i++)
scanf("%d%d%d",&s[i].lx,&s[i].rx,&s[i].h);
s[].h=; //这个的目的就是用于跳第一层,除了h有用,其他两个值都没用的
s[].lx=-;
s[].rx=;
s[N+].h=y;
s[N+].lx=x;        //这个就是目标地点
s[N+].rx=x;
qsort(s,N+,sizeof(s[]),cmp);
printf("%d\n",shorttime());
}
return ;
}