zoukankan      html  css  js  c++  java
  • BZOJ4004 [JLOI2015]装备购买[贪心+线性基+高消]

    一个物品可以被其他物品表出,说明另外的每个物品看成矩阵的一个行向量可以表出该物品代表的行向量。

    于是构造矩阵,求最多选多少个物品,就是尽可能用已有的物品去表示,相当于去消去一些没必要物品,

    类似于xor的线性基,这里是实数的线性基。

    通过高斯消元不断消除,看消出几行全是零的即可。也就是看这个线性空间基底的维数或者说矩阵的秩。

    但是本题还要选的东西花费最少。可以考虑每次消元时,选择一行代表的物品花费最小的行向量来消剩下的(贪心策略)。

    如果不选这个,那么之后选出的若干个,如果真的可以表出这个的话,那将最大花费物品换成当前这个,

    一定可行(可以列式子证明)且更优。

    注意:本题丧心病狂卡精度,试验过后选择$ ext{long double} $以及$ ext{eps=1e-5}$效果最佳。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define dbg(x) cout << #x << " = " << x <<endl
     7 using namespace std;
     8 typedef long long ll;
     9 typedef long double db;
    10 typedef pair<int,int> pii;
    11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=500+3;
    21 const db eps=1e-5;//mistake
    22 db A[N][N];
    23 int val[N],ans;
    24 int n,m,tmp;
    25 
    26 int main(){//freopen("3.in","r",stdin);freopen("3.ans","w",stdout);
    27     read(n),read(m);
    28     for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)read(A[i][j]);
    29     for(register int i=1;i<=n;++i)read(val[i]);
    30     val[0]=1145141919;int i,c;
    31     for(i=1,c=1;c<=m;++c){
    32         tmp=0;
    33         for(register int l=i;l<=n;++l)if(fabs(A[l][c])>eps&&val[tmp]>val[l])tmp=l;
    34         if(!tmp)continue;
    35         if(i^tmp)swap(A[tmp],A[i]),swap(val[tmp],val[i]);
    36         ans+=val[i];
    37         for(register int l=1;l<=n;++l)if(i^l)
    38             for(register int j=m;j>=c;--j)
    39                 A[l][j]-=A[l][c]/A[i][c]*A[i][j];
    40         ++i;
    41     }
    42     printf("%d %d
    ",i-1,ans);
    43     return 0;
    44 }
    View Code

    其实本人也不太会线性代数,题解都是自己yy的,自己也不知道个所以然,比如关于消完之后全零的行向量到底本质是什么意思,为什么矩阵可以随便进行初等变换而不改变秩等等。上次翻了大学的线性代数,看了十几页就看不下去了。。哎太菜了,有空再找数学老师学吧

  • 相关阅读:
    使用静态工厂方法的好处和坏处
    xUtils3源码分析(一):view的绑定
    在laravel之外使用eloquent
    ruby里面的毒瘤
    ruby的代码风格
    ruby里面的属性访问器
    ruby里面module和class的区别
    unity里面查找所有物体
    android studio安装须知
    intellij系列ide配置
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11495092.html
Copyright © 2011-2022 走看看