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

寒假作业~就把文章和题解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;
} 

 

posted @ 2018-02-24 22:26  Twilight_Sx  阅读(295)  评论(0编辑  收藏  举报