/* ID:Klion PROG:POJ_GRIDS_1661 LANG:C 做的吐血的一题 */ /* 放假前就开始做 但是当时没有做出来 而且一直没找到哪出错了 于是就放下了,今天又拿出来了,终于在几WA之后A掉了,心里顿爽 思路:首先对木板排序,当然可以把开始点算成一块长度为0的木板 也可以不算进去。然后设置两个数组left和right分别表示从这块木板 的左(右)端到地面所需的最短时间。中间的转移方程根据是否可达某块 木板然后改变left和right的相应值 */ #include #include #include #include int N,X,Y,MAX;/*N:木板数 X,Y 起始点的坐标 MAX:每一次的最大高度*/ typedef struct {/*木板结构体*/ int x1,x2,h;/*x1:左端点 x2:右端点 h:高度*/ }Node; Node cast[1010]; int left[1010],right[1010];/*分别表示从这块木板的左(右)端点到地面所需的最短时间*/ int cmp(const void *a,const void *b) {/*按高度的从小到大排序的模板函数*/ Node *c = (Node *)a; Node *d = (Node *)b; return c->h - d->h; } int main(void) { freopen("1661.in","r",stdin); freopen("1661.out","w",stdout); int t;/*测试数*/ int i,j,k;/*零时变量*/ int flag;/*中间的标记变量*/ scanf("%d",&t); while(t--) { scanf("%d%d%d%d",&N,&X,&Y,&MAX); cast[0].x1 = cast[0].x2 = X;cast[0].h = Y;/*这两句是把起始点当成长度为0的木板加到木板数组中去*/ for(i = 1;i <= N;i++)/*读入N块木板*/ scanf("%d%d%d",&cast[i].x1,&cast[i].x2,&cast[i].h); qsort(cast,N+1,sizeof(cast[0]),cmp);/*排序*/ /*初始化left和right数组*/ memset(left,-1,sizeof(left)); memset(right,-1,sizeof(right)); for(i = 0;i <= N;i++)/*找能够直接到达地面的木板然后将left和right置为其高度值*/ { if(cast[i].h > MAX)/*如果超过每一次能下降的最大高度退出循环 后面的也都会超过*/ { break; } for(j = 0;j < i;j++) { if(cast[i].x1 > cast[j].x1 && cast[i].x1 < cast[j].x2)/*左端点在中间的某块木板中间 不能直接到达地面*/ { break; } } if(i == j)/*能够直接到达地面*/ { left[i] = cast[i].h; } for(j = 0;j < i;j++) {/*右端点在中间的某块木板中间 不能直接到达地面*/ if(cast[i].x2 > cast[j].x1 && cast[i].x2 < cast[j].x2) break; } if(i == j) {/*能够直接到达地面 right置为其高度*/ right[i] = cast[i].h; } } for(i = 1;i <= N;i++) {/*根据比其低的木板来改变相应的值*/ for(j = 0;j < i;j++) { if(cast[i].h - cast[j].h > MAX) {/*如果高度超过最大下降高度*/ continue; } flag = 1;/*标记变量*/ if((cast[i].x1 < cast[j].x1) || (cast[i].x1 > cast[j].x2)) flag = 0;/*如果左端点不落在cast[j]木板中间 那么就不能由cast[j]得到cast[i]的left值*/ for(k = j+1;k < i && flag;k++) {/*被中间某块木板隔开了*/ if(cast[i].x1 > cast[k].x1 && cast[i].x1 < cast[k].x2) break; } if(k == i && flag) {/*如果符合上面的条件*/ /*如果left[j]的值大于0且(left[i]的值还没算出来或者比现在的要大)*/ if(left[j] >= 0 && (-1 == left[i] || (left[i] > (left[j]+cast[i].x1-cast[j].x1+cast[i].h-cast[j].h)))) left[i] = left[j]+cast[i].x1-cast[j].x1+cast[i].h-cast[j].h; /*如果right[j]的值大于0且(left[i]的值还没算出来或者比现在的要大)*/ if(right[j] >= 0 && (-1 == left[i] || (left[i] > (right[j]+cast[j].x2-cast[i].x1+cast[i].h-cast[j].h)))) left[i] = right[j]+cast[j].x2-cast[i].x1+cast[i].h-cast[j].h; } /*下面是右端点 和左端点相似*/ flag = 1; if(cast[i].x2 < cast[j].x1 || cast[i].x2 > cast[j].x2) flag = 0; for(k = j+1;k < i && flag;k++) { if(cast[i].x2 > cast[k].x1 && cast[i].x2 < cast[k].x2) break; } if(k == i && flag) { if(left[j] >= 0 && (-1 == right[i] || (right[i] > (left[j]+cast[i].x2-cast[j].x1+cast[i].h-cast[j].h)))) right[i] = left[j]+cast[i].x2-cast[j].x1+cast[i].h-cast[j].h; if(right[j] >= 0 && (-1 == right[i] || (right[i] > (right[j]+cast[j].x2-cast[i].x2+cast[i].h-cast[j].h)))) right[i] = right[j]+cast[j].x2-cast[i].x2+cast[i].h-cast[j].h; } } } printf("%d\n",left[N]