码迷,mamicode.com
首页 > 其他好文 > 详细

线性空间和异或空间(线性基)bzoj4004贪心+高斯消元

时间:2019-03-14 20:10:47      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:cin   价格   scanf   else   cstring   bit   组合   def   can   

线性空间:是由一组基底构成的所有可以组成的向量空间
  对于一个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\n",cnt,ans); 
}

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

#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;
}

 

线性空间和异或空间(线性基)bzoj4004贪心+高斯消元

标签:cin   价格   scanf   else   cstring   bit   组合   def   can   

原文地址:https://www.cnblogs.com/zsben991126/p/10532971.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!