判断两点间是否有整数点共线

本文解析了一道有趣的算法题——杭电1577WisKey的眼镜神,通过数学方法判断两个点之间是否会被其它点遮挡,介绍了如何利用辗转相除法来判断两点连线是否经过整数点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

杭电1577WisKey的眼神

Problem Description
WisKey的眼镜有500多度,所以眼神不大好,而且他有个习惯,就是走路喜欢看着地(不是为了拣钱哦^_^),所以大家下次碰见他的时候最好主动打下招呼,呵呵.
但是Rabbit总是喜欢扮神秘,一天WisKey去食堂排队等着买饭,突然收到一道短消息,是Rabbit发的,”呵呵,又看见你了,你没看到我吧”.WisKey马上拉长脖子扫描食堂,可是就是看不到,再发短信问Rabbit在哪,Rabbit回信曰”我已经在寝室了”.WisKey无语....
假设食堂是个正方形,食堂中心坐标为(0,0),长度为2*L, WisKey保证在食堂内.
因为是吃饭高峰期,所以每个点上都站着人,当某些人处在同一直线上时就有可能被前面的人挡住.
聪明的ACMer请你帮帮WisKey,告诉他能不能看见Rabbit.
 (还有一幅图http://acm.hdu.edu.cn/showproblem.php?pid=1577)
Input
输入L,sx,sy,px,py; L<=1000,sx,sy是WisKey的坐标,px,py是Rabbit的坐标.
以L=0为结束.
 
Output
对于每组输入数据,能看见输出”Yes”,看不见输出”No”.
Rabbit不在食堂输出”Out Of Range”.
 
Sample Input
5 0 0 1 1
5 0 0 2 0
5 0 0 6 6
5 0 0 -1 -1
0
 


Sample Output
Yes
No
Out Of Range
Yes


只能说这道题很棒,让我学会了很多。也让我认识到我喜欢不看清题目就去打代码,这是很危险的,以后要好好改正。闲话不多说,我们入题吧。


1;看清题意,明白隐藏内容。

每个点上都站着人,当某些人处在同一直线上时就有可能被前面的人挡住.;看这句话,很有挖掘潜能的,每个点;意味着每个整数点都会有人挡着也就是说他们两个人的连线上不能有整数点(xy都是整数的点)。


2;怎么把题意思维化代码化。(感觉这点超难的还请教了师兄好久)
两个人的连线上没有整数点。题意。
先介绍一个超时的代码出来,可以以后用;
判断三点共线的公式为,(x2-x1)*(y3-y1)=(y2-y1)*(x3-x1);

然后进行枚举就OK了。然而是超时的,我们进入主题吧。


3;判断两点间是否有整数点共线。
对于点A,B之间如果存在整数点T与它们共线那么则必有AB/BC=AE/EF。(转化为相似三角形,AB为纵向距离,BC为横向距离)则AB与BC必有不唯一的公约数。所以现在的问题也就由是否存在整数点变成的横纵距离是否互质了。然而如何理解它们互质就没有整数点与他们共线呢?
解释;先说一下题的意思,题目的初始条件还有它们A,B其实是整点。

如果存在不为1的公约数k,那么则可以将AB,BC同时缩小k倍,根据三角形相似则必然存在C’点也是整数点。(因为C是整数点那么同时缩小它们的公约数倍到C’点也是整数点)。


现在可以打代码了。然而还有一点要注意(关于辗转相除while里面的数问题);
r = 1;
while(y != 0){//为什么写成r不对; 因为最前面那次不同,如果前面那次y等于0那怎么办 
r = x%y;
x = y;
y = r; 
}


////////////////////////////////////////
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
int main()
{
int l, x, y, m1, m2, k1, k2, t, r;
while(scanf("%d",&l) != EOF && l != 0){
scanf("%d %d %d %d",&m1, &m2, &k1, &k2);
if(abs(k1) > l || abs(k2) >l){
printf("Out Of Range\n");
continue;
}
x = abs(m1-k1);
y = abs(m2-k2);
if(x < y){
t = x;
x = y;
y = t;
}
r = 1;
while(y != 0){//为什么写成r不对; 因为最前面那次不同,如果前面那次y等于0那怎么办 
r = x%y;
x = y;
y = r; 
}
if(x == 1){
printf("Yes\n");
}
else printf("No\n"); 
}

return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值