题意:中文 https://vjudge.net/problem/POJ-1661
题解:设两个dp数组,dpl[i]存 从第i块板左边到地上所花的最短时间,dpr[i]存右边的。
将所有板按高度排序 ,从地面到人分别编号为0,1~n, n+1
坑:dp方程写错了个字母。
一开始只用了一个dp数组(还改半天)
没考虑同一高度
人与地板算入dp数组时的赋值
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<vector> #include<cstring> #include<set> #include<algorithm> #include<stack> #include<string> #include<cstdio> #define _for(i, a, b) for (int i = (a); i<(b); ++i) using namespace std; const int N = 1e3 + 5; struct plat { int l, r, h; }p[N]; int dpl[N],dpr[N];//从第e块plat边缘一直掉到地上所需的最短时间 bool cmp(plat a, plat b) { return a.h < b.h; } int find(int x,int now) { if (now == 0) return 0; else for (int i = now-1; i >=0; i--) { if (p[i].h == p[now].h)continue;//改:同高度 if (p[i].l <= x&&p[i].r >= x) return i; } return 0;//直接掉到地上 } //大改:算法错误。 int main() { int t; cin >> t; while (t--) { _for(i, 0, N) dpl[i]=dpr[i] = 1e9; int n, x, y, mn; cin >> n >> x >> y >> mn; _for(i, 1, n+1) {cin >>p[i].l>>p[i].r>>p[i].h;} p[n+1].l = p[n+1].r = x; p[n+1].h = y; p[0].l = -2e6; p[0].r = 2e6; p[0].h = 0; //改:考虑掉到地上,不能这样改。 sort(p, p + n+2,cmp); //查找落到下面的那一块:可以排序后二分 _for(i, 1, n+1) { int idl= find(p[i].l,i), idr= find(p[i].r,i); if (idl == 0) { if (p[i].h <= mn) dpl[i] = p[i].h; } else if (p[i].h - p[idl].h <= mn)
{ dpl[i] = min(dpl[i], dpl[idl] + p[i].h - p[idl].h + p[i].l - p[idl].l);
dpl[i] = min(dpl[i], dpr[idl] + p[i].h - p[idl].h - p[i].l + p[idl].r);} if (idr == 0) { if (p[i].h <= mn) dpr[i] = p[i].h; } else if (p[i].h - p[idr].h <= mn) { dpr[i] = min(dpr[i], dpl[idr] + p[i].h - p[idr].h + p[i].r - p[idr].l); dpr[i] = min(dpr[i], dpr[idr] + p[i].h - p[idr].h - p[i].r + p[idr].r); } } int i = n + 1; int idl = find(p[i].l, i); if (idl == 0) { if (p[i].h - p[idl].h <= mn) dpl[i] = p[i].h - p[idl].h; } else if (p[i].h - p[idl].h <= mn) { dpl[i] = min(dpl[i], dpl[idl] + p[i].h - p[idl].h + p[i].l - p[idl].l); dpl[i] = min(dpl[i], dpr[idl] + p[i].h - p[idl].h - p[i].l + p[idl].r); } cout << dpl[n+1]<<endl; } system("pause"); }