地址:http://poj.org/problem?id=1661
解法:这题说穿了还真没什么难的,将所有线段按高度排序,然后dp求解一个lefttime[i],righttime[i]分别表示从i线段左端跳下去和右端跳下去的最短落地时间(如果会摔死直接返回MAX),既然保证有解也就不用判断MAX了。
PS:为什么要把这题贴出来呢?因为我昨天晚上居然傻逼呵呵的先用线段树去求每个端点的下一个线段,然后离散化,然后反去求原来的值,写了200+的代码调不动。。。
没看懂?参见小媛大神的博客:http://blog.youkuaiyun.com/zxy_snow/article/details/5771229
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
#define N 1010
#define MAX 100000000
struct Segment{
int lx,rx,h;
bool operator <(const Segment t)const{
return h>t.h;
}
}seg[N];
int n,maxh;
int lefttime[N];
int righttime[N];
int mintime(int L,int lr){
int i,x,h;
if(lr){
x=seg[L].lx;
}
else{
x=seg[L].rx;
}
h=seg[L].h;
for(i=L+1;i<=n;i++){
if(seg[i].lx<=x&&x<=seg[i].rx){
break;
}
}
if(i==n+1){
if(h>maxh) return MAX;
else return h;
}else{
if(h-seg[i].h>maxh) return MAX;
}
int ltime=x-seg[i].lx+h-seg[i].h;
int rtime=seg[i].rx-x+h-seg[i].h;
if(lefttime[i]==-1)
lefttime[i]=mintime(i,1);
if(righttime[i]==-1)
righttime[i]=mintime(i,0);
return min(ltime+lefttime[i],rtime+righttime[i]);
}
int main(){
int i,j,t;
while(scanf("%d",&t)!=EOF){
while(t--){
memset(lefttime,-1,sizeof(lefttime));
memset(righttime,-1,sizeof(righttime));
int x,y;
scanf("%d %d %d %d",&n,&x,&y,&maxh);
seg[0].lx=seg[0].rx=x;
seg[0].h=y;
for(i=1;i<=n;i++){
scanf("%d %d %d",&seg[i].lx,&seg[i].rx,&seg[i].h);
}
sort(seg,seg+n+1);
printf("%d\n",mintime(0,0));
}
}
return 0;
}