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;
}
浙公网安备 33010602011771号