P1535-HAOI2014【穿越封锁线】


十分有趣的一道几何题,本来就繁琐的题,碰上本来就容易多 的蒟蒻的我。。。真是无力Orz
描述 Description
 某敌战区是一个封闭的多边形,用相邻的顶点集合P1(x1,y1),P2(x2,y2),......, Pn(xn,yn)表示。
我方侦察员ZDM-007要穿越敌战区的封锁线,为了安全起见,ZDM-007行走的路线垂直于X坐标轴,从南向北穿越。
现在已知侦察员ZDM-007所处的位置,你能算出他在穿越封锁线时,在敌战区内的路线距离是多少吗?(Y方向的长度)
::点击图片在新窗口中打开::
输入格式 Input Format
 第一行:    N        表示多边形顶点的个数
接下来N行:   Xi  Yi      表示多边形的顶点坐标  (逆时针顺序给出)
最后一行:  Xa  Ya    表示侦察员所处的位置
输出格式 Output Format
 侦察员穿越封锁线时,在敌战区内的路线距离(Y方向的长度),仅输出总的路线长度的整数部分。

可以把侦查员走过的路径(竖直向上)直接看做一条线段,每次都从多边形一条与其相交边的交点进入敌占区而从下一个交点出来。所以我们只要合理的考虑到所有的交点用(偶数点-上一个奇数点)即可,当然还得考虑到路径与一条边重合的情况。。。
分类方式:
1.边i(不包括端点)是否与路径有交点;
2.边i是否与路径重合;
在2不成立的情况下:
3.右端点是否在路径上(若是则继续判断边i与i+1是否在路径的同一侧)
4.当3不成立时再判断一下边i的左端点是否在路径上。
。。。
我对我事无巨细已经到无比纠结的风格表示Orz。
Co de:

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
using namespace std;
struct da
{
int x1,y1,x2,y2;
}L[120];
int N,Xa,Ya,T=1;
double P[120],Ans=0;
void init()
{
cin>>N;
for(int i=1;i<=N;i++)
{
cin>>L[i].x1>>L[i].y1;
L[i-1].x2=L[i].x1,L[i-1].y2=L[i].y1;
}
L[N].x2=L[1].x1,L[N].y2=L[1].y1;//存边
cin>>Xa>>Ya;
//cout<<"+++++++++++++++++++++++++++++++"<<endl;
//cout<<"+++++++++++++++++++++++++++++++"<<endl;
//cout<<"+++++++++++++++++++++++++++++++"<<endl;
//for(int i=1;i<=N;i++)
//printf("%d %d %d %d\n",L[i].x1,L[i].y1,L[i].x2,L[i].y2);
}
void work_out(int i)//按y=kx+b计算交点
{
double k=(L[i].y2-L[i].y1)*1.0/(L[i].x2-L[i].x1);
double b=L[i].y1-k*L[i].x1;
P[T++]=k*Xa+b;
}
void checkk_x2(int i)
{
if(L[i].x1<Xa&&L[i+1].x2<Xa || L[i].x1>Xa&&L[i+1].x2>Xa)
return;
else P[T++]=L[i].y2;
}
int main()
{
init();
for(int i=1;i<=N;i++)
{
if((L[i].x1>Xa&&L[i].x2<Xa)||(L[i].x1<Xa&&L[i].x2>Xa))
work_out(i);
else
{
if(L[i].x1==Xa&&L[i].x2==Xa)
{
Ans+=abs(L[i].y1-L[i].y2);
i++;
}
else
{
if(L[i].x2==Xa)
{
checkk_x2(i);
i++;
}
else if(L[i].x1==Xa)
P[T++]=L[i].y1;
}
}
}//分类如上。。。
sort(P+1,P+T);
for(int i=1;i<T;i++)
if(i%2==0)
Ans+=P[i]-P[i-1];
cout<<int(Ans)<<endl;
return 0;
}


OK。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值