【算法】高斯消元&线性代数

寒假作业~就把文章和题解3道题的代码扔在这里啦——链接: https://pan.baidu.com/s/1kWkGnxd 密码: bhh9

1.HNOI2013游走

#include <bits/stdc++.h>
using namespace std;
#define maxn 600
#define db double
int n, m, degree[maxn];
db f[maxn][maxn], ans[maxn], fans;
bool dis[maxn][maxn];

struct edge
{
    int x, y;
    db ans;
}R[maxn * maxn];

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); }
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
    return x * k;
}

bool cmp(edge a, edge b)
{
    return a.ans > b.ans;
}

void Gauss()
{
    for(int i = 1; i <= n; i ++)
    {
        int now = i, j = i;
        for(int j = i + 1; j <= n; j ++)
            if(fabs(f[j][i]) > fabs(f[now][i])) now = j;
        if(i != now)
        {
            for(int k = 1; k <= n + 1; k ++)
                swap(f[i][k], f[now][k]);
        }
        for(int j = i + 1; j <= n + 1; j ++)
            f[i][j] /= f[i][i];
        for(int j = 1; j <= n; j ++)
        {
            if(j == i) continue;
            for(int k = i + 1; k <= n + 1; k ++)
                f[j][k] -= f[j][i] * f[i][k];
        }
    }
}

int main()
{
    n = read(), m = read();
    for(int i = 1; i <= m; i ++)
    {
        int x = read(), y = read();
        R[i].x = x, R[i].y = y;
        degree[x] ++, degree[y] ++, dis[x][y] = dis[y][x] = true;
    }
    n -= 1;
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            if(dis[i][j]) f[i][j] = - (1 / (db) degree[j]);
            else if(i == j) f[i][j] = 1;
    f[1][n + 1] = 1;
    Gauss();
    for(int i = 1; i <= n; i ++) ans[i] = f[i][n + 1];
    for(int i = 1; i <= m; i ++)
        R[i].ans = ((db) ans[R[i].x] / (db) degree[R[i].x]) + ((db) ans[R[i].y] / (db) degree[R[i].y]);
    sort(R + 1, R + 1 + m, cmp);
    for(int i = 1; i <= m; i ++)
        fans += (db) i * R[i].ans;
    printf("%.3lf\n", fans);
    return 0;
}

2.USACO灯

#include <bits/stdc++.h>
using namespace std;
#define maxn 60
int n, m, a[maxn][maxn], ans[maxn], fans = 999999, tot;

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); }
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
    return x * k;
}

void Gauss()
{
    for(int i = 1; i <= n; i ++)
    {
        int now = i, j = i;
        while(j <= m && !a[j][i]) j ++;
        if(j > m) continue;
        if(now != j)
        {
            for(int k = 1; k <= n + 1; k ++)
                swap(a[now][k], a[j][k]);
        }
        for(int j = 1; j <= n; j ++)
            if(j != i && a[j][i])
            {
                for(int k = 1; k <= n + 1; k ++)
                    a[j][k] ^= a[i][k];
            }
    }
}

void dfs(int now)
{
    if(tot >= fans) return;
    if(!now)
    {
        fans = min(fans, tot);
        return;
    }
    if(a[now][now]) //不是自由元
    {
        int tem = a[now][n + 1];
        for(int i = now + 1; i <= n; i ++)
            if(a[now][i]) tem ^= ans[i];
        ans[now] = tem;
        if(tem) tot ++;
        dfs(now - 1);
        if(tem) tot --;
    }
    else
    {
        ans[now] = 0;
        dfs(now - 1);
        tot ++;
        ans[now] = 1;
        dfs(now - 1);
        tot --;
    }
}

int main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i ++)
        a[i][i] = 1, a[i][n + 1] = 1;
    for(int i = 1; i <= m; i ++)
    {
        int x = read(), y = read();
        a[x][y] = 1, a[y][x] = 1;
    }
    Gauss();
    dfs(n);
    printf("%d", fans);
} 

3.NOIP2004虫食算

#include <bits/stdc++.h>
using namespace std;
#define maxn 40
int n, f[maxn][maxn], g[maxn][maxn], d[maxn], x[maxn];
char s[3][maxn];
bool vis[maxn], flag;

int GCD(int x, int y)
{
    int z;
    while(y)
    {
        z = x % y;
        x = y, y = z;
    }
    return x;
}

int LCM(int x, int y)
{
    return (x * y / GCD(x, y));
} 

void check()
{
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= n; i ++)
    {
        int sum = 0;
        for(int j = 2; j <= n; j ++)
            sum += d[j] * g[i][j];
        if(sum % f[i][i]) return;
        sum /= f[i][i];
        if(sum < 0 || sum >= n || vis[sum]) return;
        vis[x[i] = sum] = true;
    }
    flag = true;
}

void solve()
{
    for(int p = 1; p <= n; p ++)
    {
        int now = p;
        for(int i = p + 1; i <= n; i ++)
            if(abs(f[i][p]) > abs(f[now][p])) now = i;
        if(now != p)
        {
            for(int i = 1; i <= n; i ++)
                swap(f[now][i], f[p][i]), swap(g[now][i], g[p][i]);
        }
        for(int i = 1; i <= n; i ++)
            if(i != p && f[i][p])
            {
                int lcm = LCM(f[i][p], f[p][p]);
                int d1 = lcm / f[i][p], d2 = lcm / f[p][p];
                for(int j = 1; j <= n; j ++)
                {
                    f[i][j] = f[i][j] * d1 - f[p][j] * d2;
                    g[i][j] = g[i][j] * d1 - g[p][j] * d2;
                }
            }
    }
}

void dfs(int u)
{
    if(u == 1)
    {
        check();
        if(flag)
        {
            for(int i = 1; i < n; i ++)
                printf("%d ", x[i]);
            printf("%d\n", x[n]);
            exit(0);
        }
        return;
    }
    d[u] = 0, dfs(u - 1);
    d[u] = 1, dfs(u - 1);
}

int main()
{
    scanf("%d", &n);
    scanf("%s%s%s", s[0] + 1, s[1] + 1, s[2] + 1);
    for(int i = 1; i <= n; i ++)
        for(int j = 0; j <= 2; j ++)
            if(j < 2) f[i][s[j][i] - ‘A‘ + 1] += 1;
            else f[i][s[j][i] - ‘A‘ + 1] -= 1;
    for(int i = 1; i <= n; i ++)
        g[i][i] = n, g[i][i + 1] = -1;
    solve();
    dfs(n);
    return 0;
} 

原文地址:https://www.cnblogs.com/twilight-sx/p/8467871.html

时间: 2024-10-10 06:26:51

【算法】高斯消元&线性代数的相关文章

矩阵算法 高斯消元 行列式 矩阵的秩

今天学习一下矩阵的基本算法 高斯消元是解线性方程组的有力工具. 基本思想是通过将增广矩阵经过行初等变化变成简化阶梯形矩阵. 下面采用的是列主元高斯消元法,复杂度为O(n^3). 很容易根据高斯消元法的过程得出行列式和秩的算法. 代码: /********************************************************* * ------------------ * * author AbyssalFish * ***************************

算法复习——高斯消元(ssoi)

题目: 题目描述 Tom 是个品学兼优的好学生,但由于智商问题,算术学得不是很好,尤其是在解方程这个方面.虽然他解决 2x=2 这样的方程游刃有余,但是对于下面这样的方程组就束手无策了.x+y=3x-y=1于是他要你来帮忙.给定一个线性多元一次方程组,请你求出所有未知数的解.保证在 int 范围内可以处理所有问题. 输入格式 输入文件的第一行一个数字 N(1≤N≤100),表示给定的方程组中的未知数的个数,同时也是这个方程组含有的方程个数.第 2 到 N+1 行,每行 N+1 个数.每行的前 N

[算法模板]高斯消元

高斯消元用于求解线性方程. 贴一下代码: #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define maxn 150 int n; double a[maxn][maxn]; using namespace std; void gau(){ for(int i=1;i<=n;i++){ int line=i; for(int j=i+1;j<=n

[ACM] POJ 2947 Widget Factory (高斯消元)

Widget Factory Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 4436   Accepted: 1502 Description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to

[数论] 高斯消元(整型和浮点型)

高斯消元法: 数学上,高斯消元法(或译:高斯消去法)(英语:Gaussian Elimination),是线性代数中的一个算法,可用来为线性方程组求解,求出矩阵的秩,以及求出可逆方阵的逆矩阵.当用于一个矩阵时,高斯消元法会产生出一个"行梯阵式".(来自维基百科) 构造如下方程: a[0][0]*X0 + a[0][1] *X1 + a[0][2]*X2+...........a[0][n-1]*Xn-1   =  a[0][n] a[1][0]*X0 + a[1][1] *X1 + a

高斯消元【转】

转载注明出处 高消一直是ACM中高层次经常用到的算法,虽然线性代数已经学过,但高消求解的问题模型及高消模板的应用变化是高消的最复杂之处. 先介绍一下高消的基本原理:引入互联网czyuan的帖子: 高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵. 高斯消元法的原理是: 若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. 所以我们可以用初等行变换把增广矩阵转换为行阶梯阵,然后回代求出方程的解. 以上是线性代数课的回顾,

BZOJ 1013 [JSOI2008]球形空间产生器sphere 【高斯消元】

Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器. HINT 1<=n<=10 提示:给出两个定义:1. 球心:到球面上任意一点距离都相等的点.2. 距离:设两个n为空间上的点A, B的坐标为(a1, a2, …, an), (b1, b2, …, bn),则AB的距离定义为:dist = sqrt( (a1-b1)^2 +

线代之高斯消元

数学上,高斯消元法(或译:高斯消去法),是线性代数规划中的一个算法,可用来为线性方程组求解.但其算法十分复杂,不常用于加减消元法,求出矩阵的秩,以及求出可逆方阵的逆矩阵.不过,如果有过百万条等式时,这个算法会十分省时.一些极大的方程组通常会用迭代法以及花式消元来解决.当用于一个矩阵时,高斯消元法会产生出一个"行梯阵式".高斯消元法可以用在电脑中来解决数千条等式及未知数.亦有一些方法特地用来解决一些有特别排列的系数的方程组. 2968: Lights  Time Limit(Common

高斯消元(一)——基础概念和加减消元

如果遇到这种解方程的题目,想把它每个未知数写出公式可不容易,而在不知道解的数据范围的时候,二分枚举什么的和没做没区别,所以这里引入了高斯消元对此进行解答. 高斯消元简直就是为计算机量身打造的解n元一次方程组的利器,虽然在算法竞赛中并不会考像加减消元这种容易的题目,但是这作为它的基础,还是需要讨论一下的. 1.基础概念 高斯消元是指,用第i个式子将它下方的n-i个式子的第i个未知数系数通过加减消元法变为零,然后反过来求解所有未知数的过程. 2.加减消元 为了方便描述,我们将每个式子按照同一个未知数