http://poj.org/problem?id=1925
蜘蛛侠要从最左荡到最右
荡的过程中不能着地 问最少荡多少次
荡点 在荡的过程中高度不变
要以 荡点(0...1000000)找最小答案进行更新
代码及其注释:
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> #include<cmath> #include<stack> #include<algorithm> using namespace std; const int N=5005; int X[N];//建筑的x坐标 int H[N];//建筑的高度 int ans;//最终答案 int num[1000005];//x处的点 要想荡到这里 最少多少次 int n; int findlx(int h)//高度为 h 是可由左边 多少范围内的点 往这荡 { double x=(double)abs(H[0]-h); double z=(double)h; return int(z*cos(asin(x/z))); } int main() { int K; scanf("%d",&K); while(K--) { scanf("%d",&n); for(int i=0;i<n;++i) { scanf("%d %d",&X[i],&H[i]); } ans=N; memset(num,-1,sizeof(num));//初始化 num[X[0]]=0;//起点 荡 0 次 for(int i=1;i<n;++i) { int lx=X[i]-findlx(H[i]);//向左偏移 for(int j=max(X[0],lx);j<X[i];++j)//遍历 { if(num[j]!=-1)//左边点 有可能 { if(X[i]+X[i]-j>=X[n-1])//更新答案 { ans=min(ans,num[j]+1); continue; } if(num[X[i]+X[i]-j]==-1||num[X[i]+X[i]-j]>num[j]+1)//更新右边的点 { num[X[i]+X[i]-j]=num[j]+1; } } } } if(ans==N) printf("-1\n"); else printf("%d\n",ans); } return 0; }