题目刚一看没有什么思路,不知道状态如何定义,后来仔细想了想。状态d[i]可以定义为从i坐标跳到终点花费的最少步骤时多少。显然,这样的定义用递归实现比较方便,也许时最近刷的dp都是用递归解决的。但是递归比较慢,导致超时。最后一直在想有没有什么方法剪掉一些状态,始终也没有想到什么好的办法。后来看了别人的题解。用的是递推。状态定义为,到达i坐标时花费的最少步数。自己按照这个思路写了一遍。下面时代码。注意坐标用long long 型。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAX = 1000010;
const int MAXN = 10010;
const int INF = 100000000;
int d[MAX];
struct Node{
long long x, y;
}p[MAXN];
bool f(int u, int v, int i){
return (p[i].x-u)*(p[i].x-u) + (p[i].y-v)*(p[i].y-v) <= p[i].y*p[i].y;
}
int n, h;
int dp(){
d[p[0].x] = 0;
for (int i = 1; i<n; i++){
for (int j = 1; j<=p[i].x-p[0].x; j++){
int u = p[i].x-j, v = p[i].x+j;
if (v >= p[n-1].x) v = p[n-1].x;
if (f(u,h,i)){
if (d[u] != -1){
if (d[v] == -1) d[v] = d[u] + 1;
else d[v] = min(d[v], d[u]+1);
}
}
else break;
}
}
return d[p[n-1].x];
}
int main(){
int T;
scanf("%d",&T);
while (T--){
memset(d, -1, sizeof(d));
scanf("%d",&n);
for (int i = 0; i<n; i++){
scanf("%d%d",&p[i].x, &p[i].y);
}
h = p[0].y;
int ans = dp();
if (ans >= INF) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}