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;
}