zoukankan      html  css  js  c++  java
  • 【BZOJ4004】[JLOI2015] 装备购买(向量线性基)

    点此看题面

    大致题意: 给定(n)(m)维向量,每个向量有一个代价。规定若一个向量能用所持向量以任意系数相加得到,则这个向量就不必选择。求选择的最大向量数目以及此时所花的最小代价。

    线性基

    如果你对线性基的认知仅仅停留在异或的层面,那么这道题就无比棘手了。

    事实上,异或的线性基可以看作特殊的线性基,把一个数分成一个向量,向量的每维只有(0/1)两种数。(类比(01)矩阵,可以叫做(01)线性基?)

    那么一般的线性基该如何维护呢?这个过程实际上类似于高斯消元,大概可以看作异或线性基和高斯消元的结合,实现可以详见代码。

    贪心

    因此,对于这道题,我们贪心地对向量按代价排序,每次判断能否插入线性基,能插就插。

    至于贪心的依据,我相信是比较显然的,这里就不予证明了。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 500
    #define eps 1e-8
    #define DB long double
    using namespace std;
    int n,m;
    struct Vec//存储一个向量
    {
    	int v;DB a[N+5];I DB& operator [] (CI x) {return a[x];}
    	I bool operator < (Con Vec& o) Con {return v<o.v;}//按代价排序
    }s[N+5];
    class LinearBasis//线性基
    {
    	private:
    		int p[N+5];Vec v[N+5];
    	public:
    		I bool Ins(Vec x)//插入向量
    		{
    			RI i,j;DB t;for(i=1;i<=m;++i) if(fabs(x[i])>eps)//如果这一位不为0
    			{
    				if(!p[i]) {for(p[i]=1,j=i;j<=m;++j) v[i][j]=x[j];return 1;}//如果这一位还没有向量,插入成功
    				for(t=-x[i]/v[i][i],j=i;j<=m;++j) x[j]+=t*v[i][j];//类似于高斯消元,将这一位消去
    			}return 0;//插入失败
    		}
    }B;
    int main()
    {
    	RI i,j;for(scanf("%d%d",&n,&m),i=1;i<=n;++i) for(j=1;j<=m;++j) scanf("%Lf",&s[i][j]);
    	for(i=1;i<=n;++i) scanf("%d",&s[i].v);sort(s+1,s+n+1);
    	RI t1=0,t2=0;for(i=1;i<=n;++i) B.Ins(s[i])&&(++t1,t2+=s[i].v);//贪心
    	return printf("%d %d
    ",t1,t2),0;
    }
    
  • 相关阅读:
    VSTO资源
    Windows Server 2008启用无线网络服务支持(转)
    [转载]数据库设计三大范式应用实例剖析
    C#如何为winform程序打包发布应用(图解)
    XPO学习一(获取数据库服务器时间)
    php中echo和print的区别
    isset()
    asp.net文本编辑器FCKeditor详解
    ASP.net 上传大文件问题
    StringBuilder与string和String的区别
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4004.html
Copyright © 2011-2022 走看看