CCF认证-20200601-线性分类器

欢迎访问我的CCF认证考试题解目录

题目描述

在这里插入图片描述

算法设计

如何判断两个点是否在直线的一侧呢?这里要用到一些简单的数学知识。对于一条直线 A x + B y + C = 0 Ax+By+C=0 Ax+By+C=0,如果点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)满足 A x 0 + B y 0 + C > 0 Ax_0+By_0+C>0 Ax0+By0+C>0,则点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)在该直线上方;如果点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)满足 A x 0 + B y 0 + C < 0 Ax_0+By_0+C<0 Ax0+By0+C<0,则点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)在该直线下方;如果点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)满足 A x 0 + B y 0 + C = 0 Ax_0+By_0+C=0 Ax0+By0+C=0,则点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)在该直线上。
由于题目保证不存在恰好落在直线上的点,因此我们无需考虑点落在直线上的情况。因此,如果两个点都落在直线上方或直线下方,那么这两个点一定在直线的一侧;反之,如果一个点落在直线上方,一个点落在直线下方,那么这两个点一定不在直线的一侧。
由于输入的点最多只有1000个,输入的直线最多也只有20条,因此我们可以针对输入的每条直线暴力查找每一个同类的点是否位于该直线的一侧。算法的时间复杂度为 O ( m n ) O(mn) O(mn)

C++代码

#include <bits/stdc++.h>
using namespace std;
using gg = long long;
int main() {
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);
    gg ni, mi;
    cin >> ni >> mi;
    vector<vector<array<gg, 2>>> points(2);
    gg xi, yi, ai, bi, ci;
    string typei;
    while (ni--) {
    
    
        cin >> xi >> yi >> typei;
        points[typei[0] - 'A'].push_back({
    
    xi, yi});
    }
    while (mi--) {
    
    
        cin >> ai >> bi >> ci;
        for (auto& p : points) {
    
    
            for (gg i = 1; i < p.size(); ++i) {
    
    
                if ((ai + bi * p[i][0] + ci * p[i][1] > 0) ^ (ai + bi * p[0][0] + ci * p[0][1] > 0)) {
    
    
                    cout << "No\n";
                    goto loop;
                }
            }
        }
        cout << "Yes\n";
    loop:;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/richenyunqi/article/details/108163673