第一版:通过题意模拟,暴力枚举,先通过每条线面临的第一个点去初始化线的上侧是A类别还是B类别,然后再去判断后续的点;
注意:点的坐标和直线的参数数据类型因开为 long long,否则计算时会溢出,导致结果出错。
#include<iostream>
using namespace std;
struct point
{//点
long long x, y;//开为int下面计算会溢出报错
char type;
};
struct line
{//直线
long long a, b, c;//开为int下面计算会溢出报错
};
point p[1005];
line l[25];
int main()
{
int n, m, i, j;
cin >> n >> m;
for (i = 0; i < n; i++)
cin >> p[i].x >> p[i].y >> p[i].type;
for (i = 0; i < m; i++)
cin >> l[i].a >> l[i].b >> l[i].c;
int flag, flagA, flagB;
for (i = 0; i < m; i++)
{
flag = 0;//用每条线面临的第一个点初始化,在线上侧的falg初始化为1
if ((l[i].a + l[i].b * p[0].x + l[i].c * p[0].y) > 0)
{
if (p[0].type == 'A')
flagA = 1, flagB = 0;
else
flagB = 1, flagA = 0;
}
else
{
if (p[0].type == 'A')
flagA = 0, flagB = 1;
else
flagB = 0, flagA = 1;
}
if (flagA == 1)//如果A在线的上侧
{
for (j = 1; j < n; j++)
{
if ((l[i].a + l[i].b * p[j].x + l[i].c * p[j].y) > 0 && p[j].type != 'A')
{//该点在线的上侧但不是A类别
flag = 1;//标记非法情况发生
cout << "No\n";
break;
}
else if ((l[i].a + l[i].b * p[j].x + l[i].c * p[j].y) < 0 && p[j].type != 'B')
{//该点在线的下侧但不是B类别
flag = 1;//标记非法情况发生
cout << "No\n";
break;
}
}
if (!flag)
cout << "Yes\n";
}
else//如果B在线的上侧
{
for (j = 1; j < n; j++)
{
if ((l[i].a + l[i].b * p[j].x + l[i].c * p[j].y) > 0 && p[j].type != 'B')
{//该点在线的上侧但不是B类别
flag = 1;
cout << "No\n";
break;
}
else if ((l[i].a + l[i].b * p[j].x + l[i].c * p[j].y) < 0 && p[j].type != 'A')
{//该点在线的下侧但不是A类别
flag = 1;
cout << "No\n";
break;
}
}
if (!flag)
cout << "Yes\n";
}
}
return 0;
}
第二版:用两个比特位表示z类型的点出现在线的哪一个侧,比如:01 表示出现在线的上侧 10表示下侧。
#include<iostream>
using namespace std;
const int N = 1005;
struct point
{
long long x, y;
char type;
}p[N];
int n, m;
int get(int a, int b, int c, char z)
{
int s = 0;//用两个比特位表示z类型的点出现在线的哪一个 01 表示出现在线的上侧 10表示下侧
for (int i = 0; i < n; i++)
{
if (p[i].type == z)
{
if ((a + b * p[i].x + c * p[i].y) > 0)
s |= 1;// 出现在上侧,用s或上01
else
s |= 2;//出现在下侧,用s或上10
}
}
return s;
}
bool check(int a, int b, int c)
{
int s1 = get(a, b, c, 'A'), s2 = get(a, b, c, 'B');
if (s1 == 3 || s2 == 3)// 出现 s=11 的情况,说明一个类型的点在线的两边都出现了
return false;
if (s1 & s2)// 出现 10 10 或 01 01 的情况,说明两个类型的点在同一侧
return false;
return true;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> p[i].x >> p[i].y >> p[i].type;
int a, b, c;
while (m--)//对每一条线进行处理
{
cin >> a >> b >> c;
if (check(a, b, c))
cout << "Yes\n";
else
cout << "No\n";
}
return 0;
}