原题链接
解题思路
容易想到只要把点的坐标带入方程看结果与0的大小可以判断出点在直线左侧还是右侧。
对于每一个方程(直线),判断的过程如下:
记录下每个点的信息(包括哪一类),判断的时候先计算第一个点位于直线左边还是右边,然后看剩余的点是否和第一个点同类别:
- 如果同类别,那么该点应该和第一个点在直线同一边
- 如果不同类别,那么该点应该和第一个点分处于直线两侧
源代码
#include<iostream>
using namespace std;
const int maxn = 1010;
int n, m;
struct point{
int x, y;
bool flag; // A类为true,B类为false
}points[maxn];
int a, b, c; // 方程的三个参数
bool solve(){
// 用第一个点区分A类,B类在直线的哪一边
int i = 0;
long long r = a+b*points[i].x+c*points[i].y;
for(int i=1; i<n; i++){
long long res = a+b*points[i].x+c*points[i].y;
if(points[i].flag == points[0].flag){
// 和第一个点同类别
if(r*res < 0)
return false; // 异号,同类的点不在直线同一边
}
else{
// 和第二个点不同类别
if(r*res > 0)
return false; // 同号,不同类的点在直线同一边
}
}
return true;
}
int main(){
cin>>n>>m;
int x, y;
char type;
for(int i=0; i<n; i++){
cin>>points[i].x>>points[i].y>>type;
if(type == 'A'){
points[i].flag = true;
}
else
points[i].flag = false;
}
for(int i=0; i<m; i++){
cin>>a>>b>>c;
if(solve()){
printf("Yes\n");
}
else{
printf("No\n");
}
}
return 0;
}
/*
9 3
1 1 A
1 0 A
1 -1 A
2 2 B
2 3 B
0 1 A
3 1 B
1 3 B
2 0 A
0 2 -3
-3 0 2
-3 1 1
*/
注意点
题目中提到方程的三个参数的绝对值 < = 1 0 6 <=10^6 <=106,那么把点代入的过程中即源代码中的第13和16行处的 r , r e s r, res r,res需要用long long型。
如果写成int型,测评结果为0分。