洛谷 P-3626(实数下线性基 or 高斯消元)

https://www.luogu.org/problemnew/show/P3265

题意:

有n个m项的向量,每个向量还有个花费,问最少多少花费能组合出最多的向量

思路:

高斯消元

这道题,一眼就可以知道高斯消元可写,我们把每个向量的每一项合在一起写成一个矩阵
[ a 1 . v 1 a 1 . v 2 a 1 . v 3 . . . a 1 . v m a 2 . a 1 a 2 . v 2 a 2 . v 3 . . . a 2 . v m a 3 . a 1 a 3 . v 2 a 3 . v 3 . . . a 3 . v m . . . a n . v 1 a n . v 2 a n . v 3 . . . a n . v m ] \left[ \begin{matrix} a_1.v_1 & a_1.v_2 & a_1.v_3 & ... & a_1.v_m \\ a_2.a_1 & a_2.v_2 & a_2.v_3 & ... & a_2.v_m \\ a_3.a_1 & a_3.v_2 & a_3.v_3 & ... & a_3.v_m \\ ...\\ a_n.v_1 & a_n.v_2 & a_n.v_3 & ... & a_n.v_m \\ \end{matrix} \right] a1.v1a2.a1a3.a1...an.v1a1.v2a2.v2a3.v2an.v2a1.v3a2.v3a3.v3an.v3............a1.vma2.vma3.vman.vm
我们可以求出这个矩阵的秩
[ a 1 . v 1 a 1 . v 2 a 1 . v 3 . . . a 1 . v m 0 a 2 . v 2 a 2 . v 3 . . . a 2 . v m 0 0 a 3 . v 3 . . . a 3 . v m . . . 0 0 0 . . . a n . v m ] \left[ \begin{matrix} a_1.v_1 & a_1.v_2 & a_1.v_3 & ... & a_1.v_m \\ 0 & a_2.v_2 & a_2.v_3 & ... & a_2.v_m \\ 0 & 0 & a_3.v_3 & ... & a_3.v_m \\ ...\\ 0 & 0 & 0& ... & a_n.v_m \\ \end{matrix} \right] a1.v100...0a1.v2a2.v200a1.v3a2.v3a3.v30............a1.vma2.vma3.vman.vm
这样我们就可以得到一组秩,就是每一行第一个不为0的数
因为通过消元的过程可以得知可以操作前几项来使得下面的全部为0

线性基

线性基就是模拟了一下高斯消元的过程,用 l b lb lb数组来代表基

#include

using namespace std;

#define LL long long
const int maxn = 505;
const int inf = 0x3f3f3f3f;
const int Mod = 1e9 + 7;
const double eps = 1e-5;
typedef pair<int, int> psi;

struct DX{
    double value[maxn];
    int w;

    bool operator < (const DX a) const{
        return w < a.w;
    }

}x[maxn];

int lb[maxn];

int main(int argc, char *args[]) {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) 
        for (int j = 1; j <= m; j ++) 
            cin >> x[i].value[j];
    for (int i = 1; i <= n; i ++) 
        cin >> x[i].w;
    sort(x + 1, x + 1 + n);
    int cnt = 0, sum = 0;
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            if(fabs(x[i].value[j]) > eps) {
                if(!lb[j]) {
                    lb[j] = i;
                    break;
                }else {
                    double t = x[i].value[j] / x[lb[j]].value[j];
                    for (int k = j; k <= m; k ++) 
                        x[i].value[k] -= x[lb[j]].value[k] * t;
                }
            }
        }
    }
    cout << cnt << " " << sum << endl;
    return 0;
}

你可能感兴趣的:(题解,模版,线性基)