zoukankan      html  css  js  c++  java
  • 线性空间和异或空间(线性基)bzoj4004贪心+高斯消元优秀模板

    线性空间:是由一组基底构成的所有可以组成的向量空间
      对于一个n*m的矩阵,高斯消元后的i个主元可以构成i维的线性空间,i就是矩阵的秩  
      并且这i个主元线性无关

    /*
    每个向量有权值,求最小权极大线性无关组
     
    本题是使用贪心策略的高斯消元
    由输入给出的n个物品,每个物品有m种属性,和价格price 
    如果a物品的属性可以由其他已有物品的属性组合出,那么a可以不必购买 
    问最少花掉多少钱,使得所有物品都可以组合出
    首先构建n*m矩阵,然后高斯消元
    在求第i个主元时,取价格最小的那个即可
    可用反证法证明
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 1005
    #define ld long double 
    #define esp 1e-6
    struct Vec{//带权向量 
        ld a[maxn];
        int w;
        bool operator<(const Vec & x)const {
            return w<x.w; 
        } 
    }p[maxn];
    int n,m; 
    
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>p[i].a[j];
        for(int i=1;i<=n;i++)scanf("%d",&p[i].w);
        sort(p+1,p+1+n);//按权值从小到大排即可 
        int ans=0,cnt=0;
        //高斯消元!
        int i=1,j=1,Max,Maxw;
        for(;i<=n && j<=m;i++,j++){
            Max=i;
            if(fabs(p[Max].a[j])>esp)//这里一定要加fabs,因为可能会有赋值 
                Maxw=p[Max].w;
            else Maxw=100000000;
             
            for(int k=i+1;k<=n;k++)
                if(fabs(p[k].a[j])>esp && p[k].w<Maxw){Max=k;Maxw=p[k].w;}
            if(fabs(p[Max].a[j])<esp){i--;continue;}
            
            ans+=Maxw;cnt++;
            if(Max!=i)//把Max换到第i行 
                swap(p[i],p[Max]);
            
            for(int k=1;k<=n;k++)//把每行的第j个数消为0 
                if(k!=i){
                    ld r=(ld)p[k].a[j]/p[i].a[j];
                    for(int t=1;t<=m;t++)
                        p[k].a[t]-=r*p[i].a[t];
                    p[k].a[j]=0; 
                }
        }
         
        printf("%d %d
    ",cnt,ans); 
    }

     网上找到一中贼快的高斯消元写法。。以后就用它了

    思路是枚举矩阵上的每个元素,对于每个非0的A[i][j],如果A[i][j]可以作为主元,那么就把F[j](即第j列上的主元)标记为i,因为剩下的位如何已经不重要了,所以直接退出本轮循环,继续下一行

    若A[i][j]不可以作主元,说明第j列已经有主元了,那么就用那个主元所在的行F[j]来消A[i][j]

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    using namespace std;
    #define double long double 
    const double eps=1e-5;
    struct str
    {
        double a[510];
        int v;
        bool operator < (const str &s) const
        {
            return v<s.v;
        }
    }a[510];
    int n,m,f[510];
    int main()
    {
        int i,j,k,ans1=0,ans2=0;
        double x;
        cin>>n>>m;
        for (i=1;i<=n;i++)
            for (j=1;j<=m;j++)
                cin>>a[i].a[j];
        for (i=1;i<=n;i++)
            cin>>a[i].v;
        sort(a+1,a+n+1);
        for (i=1;i<=n;i++)
            for (j=1;j<=m;j++)
                if (fabs(a[i].a[j])>eps)
                {
                    if (!f[j])//如果第j列还没有被作为秩,并且第i行第j列非0 
                    {
                        f[j]=i;
                        ans1++;
                        ans2+=a[i].v;
                        break;
                    }
                    else//反之就用A[f[j]][j]来消去A[i][j] 
                    {
                        x=a[i].a[j]/a[f[j]].a[j];
                        for (k=j;k<=m;k++)
                            a[i].a[k]-=a[f[j]].a[k]*x;
                    }
                }
        cout<<ans1<<" "<<ans2<<endl;
    }
  • 相关阅读:
    [转][Navicat for MySQL系列]Navicat如何使用(二)
    [转]Syntax error on token "Invalid Character", delete this token 的解决
    [转] valuestack,stackContext,ActionContext.之间的关系
    [转]jquery后代和子元素的区别
    python中模块、包、库的区别和使用
    python函数对象
    list深拷贝和浅拷贝
    json中load和loads区别
    变量作用域
    正则里的.*和.*?区别
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10532971.html
Copyright © 2011-2022 走看看