线代之高斯消元

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

2968: Lights 分享至QQ空间

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 8            Accepted:1

Description

 

Bessie and the cows were playing games in the barn, but the power was reset and the lights were all turned off. Help the cows get all the lights back on so they can resume their games.

The N (1 ≤ N ≤ 35) lights conveniently numbered 1..N and their switches are arranged in a complex network with M (1 ≤ M ≤ 595) clever connection between pairs of lights (see below).

Each light has a switch that, when toggled, causes that light -- and all of the lights that are connected to it -- to change their states (from on to off, or off to on).

Find the minimum number of switches that need to be toggled in order to turn all the lights back on.

It's guaranteed that there is at least one way to toggle the switches so all lights are back on.

 

Input

 

* Line 1: Two space-separated integers: N and M.

* Lines 2..M+1: Each line contains two space-separated integers representing two lights that are connected. No pair will be repeated.

 

Output

 

* Line 1: A single integer representing the minimum number of switches that need to be flipped in order to turn on all the lights.

 

Sample Input

5 6
1 2
1 3
4 2
3 4
2 5
5 3

Sample Output

 3

这个题我有两个思路一个是保存状态二分,但是显然时间很长

所以这种问题要使用高斯消元,高斯消元在解决矩阵的问题可是神神器,因为暴力得到某种状态的复杂度会很高

卿学姐的算法讲堂也有介绍这个,感兴趣的可以去看下学习下

他的引入是解方程,其实就是解矩阵,这个以前叫代入消元吧

#include<stdio.h>
#include<algorithm>
using namespace std;
int n,m,ans=0x3f3f3f3f,a[37][37],x[37];
void gauss()
{
    for(int k=1; k<=n; k++)
    {
        int bj=k;
        for(int i=k+1; i<=n; i++)if(a[i][k])
            {
                bj=i;
                break;
            }
        if(bj!=k)
            for(int j=1; j<=n+1; j++)
                swap(a[bj][j],a[k][j]);
        for(int i=k+1; i<=n; i++)
            if(a[i][k])
            {
                for(int j=1; j<=n+1; j++)
                    a[i][j]^=a[k][j];
            }
    }
}
void dfs(int xx,int tot)
{
    if(tot>ans)return;
    if(!xx)
    {
        ans=min(ans,tot);
        return;
    }
    if(a[xx][xx])
    {
        x[xx]=a[xx][n+1];
        for(int j=n; j>xx; j--)x[xx]^=x[j]&a[xx][j];
        if(x[xx])dfs(xx-1,tot+1);
        else dfs(xx-1,tot);
    }
    else
    {
        x[xx]=0;
        dfs(xx-1,tot);
        x[xx]=1;
        dfs(xx-1,tot+1);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        a[x][y]=a[y][x]=1;
    }
    for(int i=1; i<=n; i++)
        a[i][n+1]=1,a[i][i]=1;
    gauss();
    dfs(n,0);
    printf("%d",ans);
    return 0;
}

 

转载于:https://www.cnblogs.com/BobHuang/p/7450565.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值