dp
d[i] 表示从apartment到 横坐标 i 最少需跳几步。。 p[i] 建筑物 i 的横坐标, h[i]建筑物i的纵坐标
注意 由对称性,spiderman的纵坐标始终是 apartment 的高度!! 所以不需要管纵坐标!!
遍历每个建筑物。。
从横坐标 j 能跳过建筑物 i 需满足: (p[i] - j)^2 <= h[i] ^ 2 - (h[i] - h[1]) ^2
从横坐标 j 经建筑物 i 后 到达横坐标 2 * p[i] - j。。
综上, d[2 * p[i] - j] = min(d[2 * p[i] - j] , d[j] + 1)...
最后注意到达west tower的步数的处理
/*
* 1925.cpp
*
* Created on: 2011-7-8
* Author:
*/
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN = 5000 + 5;
const int MAX_X = 2000000 + 5;
const int INF = 1000000;
int n;
int p[MAXN], h[MAXN];
double scale[MAXN];
int d[MAX_X];
int main(){
int tot;
scanf("%d", &tot);
while(tot--){
scanf("%d", &n);
for(int i=1; i<=n; i++){
scanf("%d%d", &p[i], &h[i]);
// scale[i] = sqrt((double) h[i] * h[i] - (h[i] - h[1]) * (h[i] - h[1])); //注意不要用sqrt,否则TLE!! (后面比较的时候用平方)
scale[i] = h[i] * h[i] - (h[i] - h[1]) * (h[i] - h[1]);
}
memset(d, -1, sizeof(int) * MAX_X); //也可以for循环。。 d[i] = INF 为了节省时间,直接设为-1, 之后判断。。
d[p[1]] = 0;
//……
for(int i=2; i<=n; i++){
for(int j = p[i]-1; j>=p[1]; j--){
if(d[j] == -1) continue; //!!!! 直接跳过~
int gap = p[i] - j;
if(gap * gap> scale[i]) break; //gap的平方和scale比较
int aim = 2*p[i]-j;
if( (d[ aim ]==-1 || d[ aim ] > d[j] + 1) ){
d[ aim ] = d[j] + 1;
}
if(aim >= p[n] && (d[p[n]] == -1 || d[p[n]] > d[ aim ])){ //最后的处理
d[p[n]] = d[ aim ];
}
}
}
if(d[p[n]] <= 0)
printf("-1\n");
else
printf("%d\n", d[p[n]]);
}
return 0;
}