线性分类器 第19次CCF CSP认证 202006-1 C++题解

原题链接

202006-1 CSP 线性分类器

算法分析

根据高中数学学过的知识,如果两点在直线的同一侧,则其代入方程的值正负相同。据此有如下算法:

(1)取某一点,不妨设为A类型的点,代入当前所需验证的直线方程,获得一个标定值,暂记为standard。

(2)将另一个A类型的点代入直线方程,得一个值,暂记为temp。如果两点在直线的同一边,则standard * temp > 0;遍历所有的A类型点。若有任意一点使得standard * temp < 0,则意味着该条直线无法将所有A类型点分割到同一侧,输出“No”,结束本次算法。

(3)沿用(1)中的standard值对B类型的点进行比较,若对于所有B类型的点,都有standard * temp < 0,输出“Yes”;否则,输出“No”,结束本次算法。

(4)反复进行(1)~(3)直至验证所有的直线。

ps. 如果采用C++编写,上述standard和temp变量务必定义为long long类型,如果是int就WA了(亲测)(菜哭)

以下是AC代码:

代码

//采用C++
//15ms 544KB

#include <iostream>
#include <vector>
using namespace std;

struct point {
	int x;
	int y;
};

struct line {
	int a, b, c;
}; 

int main() {
	int n, m;
	vector<point> points_a;
	vector<point> points_b;
	vector<line> lines;
	cin >> n >> m;
	//读入点 
	for (int i = 0; i < n; i++) {
		point temp;
		char type;
		cin >> temp.x >> temp.y >> type;
		if (type == 'A')
			points_a.push_back(temp);
		else	points_b.push_back(temp);
	}
	//读入直线 
	for (int i = 0; i < m; i++) {
		line temp;
		cin >> temp.c >> temp.a >> temp.b;
		lines.push_back(temp);
	}
	
	//判定 
	for (int i = 0; i < m; i++) {
		bool flg = true;
		//划定标定值 
		long long standard = points_a[0].x * lines[i].a + points_a[0].y * lines[i].b + lines[i].c;
		//判断A类点 
		for (int j = 1; j < points_a.size(); j++) {
			long long temp = points_a[j].x * lines[i].a + points_a[j].y * lines[i].b + lines[i].c;
			if (temp * standard < 0) {
				cout << "No" << endl;
				flg = false;
				break;
			}
			else continue;
		}
		if (!flg)	continue; //该直线不能分隔,验证下一条 
		//判断B类点
		for (int j = 0; j < points_b.size(); j++) {
			long long temp = points_b[j].x * lines[i].a + points_b[j].y * lines[i].b + lines[i].c;
			if (temp * standard > 0) {
				cout << "No" << endl;
				flg = false;
				break;
			}
		}
		if (!flg)	continue; //该直线不能分隔,验证下一条 
		cout << "Yes" << endl;
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/waveleting/article/details/108468175