CCF 202006-1 线性分类器 CCF 202006-2 稀疏向量

CCF 202006-1 线性分类器

CCF 202006-1 线性分类器 CCF 202006-2 稀疏向量_第1张图片

思路

给定N个已知是A还是B类别的点,给定三个参数,问是否能够组成一条直线完美将两个类别分开。(数据量小,可以枚举暴力破解)
即判断在哪一侧的两类情况:1.竖线时,即a+bx:。2.斜线时,即a+bx+cy。判断当前点带入直线方程后是否大于还是小于0就可以。
如何判断直线是否完美分开A和B,即判断A和B两个类别的点同时出现在某一侧就失败

可以提前了解下什么是二分类问题:【机器学习】逻辑回归
这个问题只是单纯的给你三个参数,问你能不能用这三个参数表示出一条直线完美分开A和B两类,而大部分机器学习二分类问题是需要让你求出若干个参数来将A和B区分开来(当然不一定非要全部区分,能够达到99%区分率就可以了),如下图,可以是曲线、折线等等,不一定非要直线。
CCF 202006-1 线性分类器 CCF 202006-2 稀疏向量_第2张图片CCF 202006-1 线性分类器 CCF 202006-2 稀疏向量_第3张图片

代码实现

#include 
#include 
#include 

using namespace std;

typedef long long LL;

const int N = 1010;//点数

int n, m;
struct Point
{
    LL x, y;
    char z;//类别A还是B
}q[N];

int get(int a, int b, int c, char z)
{
    int s = 0;
    //枚举所有点判断是在直线的哪一侧
    for (int i = 0; i < n; i++)
        if (q[i].z == z)
            if (a + b * q[i].x + c * q[i].y > 0) s |= 1;//大于0情况下
            else s |= 2;
    return s;
}

bool check(int a, int b, int c)
{
    int s1 = get(a, b, c, 'A'), s2 = get(a, b, c, 'B');
    //若在二进制下s1和s2都是1或其中有一个是1则不能分开,二进制下0011为十进制3
    if (s1 == 3 || s2 == 3) return false;
    if (s1 & s2) return false;
    return true;
}

int main()
{
    cin >> n >> m;//读入n个点
    for (int i = 0; i < n; i++) cin >> q[i].x >> q[i].y >> q[i].z;
    while (m--)
    {
        int a, b, c;
        cin >> a >> b >> c;//读入三个参数,看是否构成直线分开A和B
        if (check(a, b, c)) puts("Yes");
        else puts("No");
    }
    return 0;
}

CCF 202006-2 稀疏向量

CCF 202006-1 线性分类器 CCF 202006-2 稀疏向量_第4张图片

思路

先了解下稀疏矩阵在机器学习中的应用:机器学习中的稀疏矩阵
给定两个向量,算一下两个向量的内积之和,即对应位相乘后全部相加。即找到两个向量对应位都不是0的两个数相乘就可以。

代码实现

#include 
#include 
#include 

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;//存储下标和数值

typedef long long LL;
const int N = 500010;

int n, m;//第一个和第二个向量的非零个数
PII a[N], b[N];

int main()
{
    scanf_s("%*d%d%d", &n, &m);
    for (int i = 0; i < n; i++) scanf_s("%d%d", &a[i].x, &a[i].y);
    for (int i = 0; i < m; i++) scanf_s("%d%d", &b[i].x, &b[i].y);

    LL res = 0;
    //枚举第一和第二个向量里的非0项
    for (int i = 0, j = 0; i < n && j < m; i++)
    {
        while (j < m && b[j].x < a[i].x) j++; //对每个i找到第二个向量里对应下标或i前面(左边)位置的第一个非0项
        if (j < m && b[j].x == a[i].x) res += (LL)a[i].y * b[j].y;//找到对应非0项相乘后累加
    }
    printf("%lld\n", res);
    return 0;
}

你可能感兴趣的:(CCF代码每日一练,分类,算法,数据挖掘)