Fzu 2160 Mountain climbing 模拟

来源:互联网 发布:中华大字典软件 编辑:程序博客网 时间:2024/05/04 17:37

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2160

题目大意:给你N座山的位置X和高度Y,如果两座山的山顶连线不和其它山相交,则从一座山至另外一坐山花费1单位时间,问你从每座山到最后一座山花费的时间。

解题思路:假设山为a,b,。。。,刚开始读完题一直以为必须a的高度比b高且a,b的山顶连线不和其它山相交,才能花费一单位时间过去,后来才知道高度无限制。那现在高度无限制,我们就从最后一座山N开始向前找,找到每座山X到最后一座山N的时间,同时记录X能直接到达的最远的山的位置next【X】,下次再访问完X之后直接访问next【X】就行了,当到某座山x之后不能一步到达后面的山,那么时间就是1+step【x】;因为从当前山到x只需要1时间,而从x到N在前面已经计算出来了。

同时需要说的是:对于三点坐标,如何判断中间点b与线段ab的关系?

如果(b.y-a.y)*(c.x-b.x)-(b.x-a.x)*(c.y-b.y)<0    说明b点在线段ac的下方;

如果(b.y-a.y)*(c.x-b.x)-(b.x-a.x)*(c.y-b.y)=0    说明b点在线段ac的上;

如果(b.y-a.y)*(c.x-b.x)-(b.x-a.x)*(c.y-b.y)<0    说明b点在线段ac的上方;

代码如下:

#include<stdio.h>#include<string.h>struct node{__int64 x,y,next,step;//x,y为坐标,next为当前点能到达最远点的坐标,step为到达最后一座山的时间}s[100002];bool judge(node a,node b,node c)//判断点b相对于a,c连线的位置{    if((b.y-a.y)*(c.x-b.x)-(b.x-a.x)*(c.y-b.y)<0)        return true;    return false;}int main(){    int T,n,cnt=1;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        for(int i=1;i<=n;i++)            scanf("%I64d%I64d",&s[i].x,&s[i].y);        s[n].step=0;        s[n-1].step=1;        s[n-1].next=n;        for(int i=n-2;i>0;i--)        {            int temp=i+1;            while(temp<n&&judge(s[i],s[temp],s[s[temp].next]))                temp=s[temp].next;//找到第一个无法直接到达的点            s[i].next=temp;//更新当前点的next            s[i].step=s[temp].step+1;        }        printf("Case#%d:",cnt++);        for(int i=1;i<=n;i++)            printf(" %I64d",s[i].step);        printf("\n");    }}


 

 

0 0