poj1925-Spiderman(dp)

来源:互联网 发布:霍建华横店炮王 知乎 编辑:程序博客网 时间:2024/06/05 11:47

题目连接

题意:

  蜘蛛侠从他最初所在的位置,到西塔,要经过一些高楼。而蜘蛛侠是从他所在的位置最高处出发,发出蛛丝粘在另一个楼的最高处,像荡秋千一样前行,它最远只能荡到

对应的高度。如果荡到地面就不能再前行了。问你他达到西塔最小发出的蛛丝的次数。

分析:

自己不会!看下学长的。委屈

点击打开链接

自己分析了一些:

 根据题意。“蜘蛛哥”荡到的高度都等于第一个位置的高度。那么,问题就简化了。对高度就不必关心了,只要转化横坐标的区间来判断是否可以荡。这个应该很好理解。

另外,知道一个楼的高度h和位置x,如果蜘蛛哥幸运地从地面扫过。那么,在高度为H(前面已经知道,他荡的最高的高度只与第一个有关)的上空,这样,它的范围:

由勾股定理得 :     x-√(h^2-(h-H)^2)<=r<=x+√(h^2-(h-H)^2)    

化解就为: x-√(2hH-H^2)<=r<=x+√(2hH-H^2);

这样相当于把x轴往上平移了H的高度。

理解上面的。再就是dp了。看连接吧!

还是厚着脸皮贴个代码吧!

#include<cstdio>#include<cmath>#include<cstring>#define INF 0x3f3f3f3f#include<algorithm>using namespace std;struct node{int x,y,r;}p[5005];int n,dp[1000005];int solve(){int ans=INF;memset(dp,0x3f,sizeof(dp));dp[p[1].x]=0;for(int i=2;i<=n;i++){int a=p[i].r,b=p[i].x;for(int j=a;j<b;j++){int c=2*p[i].x-j;    if(c<p[n].x) dp[c]=min(dp[c],dp[j]+1);else ans=min(ans,dp[j]+1);}}if(ans==INF) return -1;return ans;}int main(){int t;scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d %d",&p[i].x,&p[i].y);p[i].r=max(0,(int)ceil(p[i].x-sqrt(2.*p[i].y*p[1].y-1.*p[1].y*p[1].y)));}printf("%d\n",solve());}}






原创粉丝点击