Codeforces Round #284 (Div. 1) A

本文介绍了一个算法问题:如何计算在由直线划分的平面上从家到学校的最短步行路径。文章给出了两种解决方法:一种是通过判断家和学校是否位于同一侧来决定是否增加路径长度;另一种是直接使用直线方程进行判断。

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

A. Crazy Town


        n条路(直线)把无限大的平面分为若干部分,给出家和学校的坐标,每一步只能走到有“公共边”的区域,问最少要走多少步。

        自己在纸上画一下就可以发现规律,如果家和学校分别在一条直线的两边,结果就会增加1。问题就转化为了线段与直线判交的问题。


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>

using namespace std;

const double eps=1e-8;

double fabs(double x){
	if(x<0)x=-x;
	return x;
}

struct Point{
	double x,y;
	Point(double x,double y):x(x),y(y){}
	Point(){}
};

struct Line{
	Point a,b;
	Line(Point a,Point b):a(a),b(b){}
	Line(){}
};

double cross_product(Point a,Point b){
	return a.x*b.y-a.y*b.x;
}


Point home;
Point uni;
bool judge(Line line){
	Point v0=Point(line.a.x-line.b.x,line.a.y-line.b.y);
	Point v1=Point(home.x-line.b.x,home.y-line.b.y);
	Point v2=Point(uni.x-line.b.x,uni.y-line.b.y);
	return cross_product(v0,v1)*cross_product(v0,v2)<0?1:0;
}

int main(){
	double x1,y1;
	double x2,y2;
	cin>>x1>>y1>>x2>>y2;
	home=Point(x1,y1);
	uni=Point(x2,y2);
	int n;
	cin>>n;
	int ans=0;
	double a,b,c;
	for(int i=1;i<=n;i++){
		cin>>a>>b>>c;
		Line l;
		if(fabs(a)<eps){
			l=Line(Point(0,-c/b),Point(100,-c/b));
		}else if(fabs(b)<eps){
			l=Line(Point(-c/a,0),Point(-c/a,100));
		}else{
			l=Line( Point(0,-c/b) , Point(100,(-c-100*a)/b) );
		}
		if(judge(l))ans++;
	}
	cout<<ans<<endl;
	return 0;
}


        其实还有一种更简单的方法,直接把两个点坐标带入直线方程,如果结果异号,说明两点在直线两边,结果+1。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>

using namespace std;

#define ll long long

int main(){
	ll x1,y1;
	ll x2,y2;
	cin>>x1>>y1>>x2>>y2;
	int n;
	cin>>n;
	int ans=0;
	
	for(int i=1;i<=n;i++){
		ll a,b,c;
		cin>>a>>b>>c;
		ll t1=x1*a+y1*b+c;
		ll t2=x2*a+y2*b+c;
		if((t1>0&&t2<0)||(t1<0&&t2>0))ans++;
	}
	cout<<ans<<endl;
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值