poj 1925 Spiderman (dp)(疯狂TLE)

题目链接:http://poj.org/problem?id=1925

题意:给出N个点,每个点都有两个数x、y,其中x表示点的横坐标,y表示纵坐标(建筑物的高度);给出的每个点都满足y值是大于等于起始点的y值;并且这些点是按照x升序排列的。

    现在让你求:蜘蛛侠在起始点(第一个点),他想去终点(第N个点),问他最少要吐多少次丝!(他不能触碰到地,但是可以刚好相等)!

分析:DP

  dp[i]表示 :到x[i]需要的最少次数。

  很容易得到,蜘蛛侠一直是在y1高度(可以低于,但不能超过,能量守恒),为了能最少吐丝次数,那么他肯定是保持y1的高度的!

  由于他不能触碰到地,我们可以等处这样一个关系式:dis^2<=(yi*yi-(yi-y1)*(yi-y1));dis表示从左边开始到i点的距离,因此当我们在i点的时候我们可以选取的范围j是: [ x[i]-dis,x[i]-1 ]。

  从对称性可以知道:距离为j,对称点为i点是的距离是temp=2*x[i]-j。

  因此我们可以得出方程:dp[i]=min(dp[temp]+1);(初始值为inff,dp[x[1]]=0)

  值得注意的是到距离temp>=x[n]的时候temp=x[n];

  

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<map>
 4 #include<string.h>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 const int inff=1e9+7;
 9 const int maxn=2e6+10;
10 int dp[maxn];
11 int x[6000],y[6000];
12 ll dis[6000];
13 int n;
14 int main()
15 {
16     int t;
17     scanf("%d",&t);
18     while(t--){
19         scanf("%d",&n);
20 
21         for(int i=1;i<=n;i++){
22             scanf("%d %d",&x[i],&y[i]);
23             dis[i]=y[i]*y[i]-(y[i]-y[1])*(y[i]-y[1]);
24         }
25         for(int i=0;i<=x[n];i++)
26             dp[i]=inff; 
27         dp[x[1]]=0;
28         for(int i=2;i<=n;i++){
29             for(int j=x[i]-1;j>=x[1];j--){
30                 if(dp[j]==inff)continue;
31                 if((x[i]-j)*(x[i]-j)>dis[i])break;
32 
33                 int temp=2*x[i]-j;
34 
35                 dp[temp]=min(dp[temp],dp[j]+1);
36                 if(temp>=x[n])
37                     dp[x[n]]=min(dp[x[n]],dp[j]+1);
38 
39             }
40         }
41         if(dp[x[n]]==inff)
42            printf("-1\n");
43         else
44            printf("%d\n",dp[x[n]]);
45     }
46     return 0;
47 }
View Code

还有种初始值为-1,判断的,其实两种都是一样的,只是-1这个判断语句要多一点!~~!~

最坑的是请注意使用scanf、printf;不是使用cin、cout输入输出,这道题cin、cout会超时,疯狂TLE;

posted @ 2018-06-10 17:23  孟加拉国  阅读(130)  评论(0编辑  收藏  举报