BZOJ4004--装备购买

装备购买

脸哥最近在玩一款神奇的游戏,这个游戏里有 (n) 件装备,每件装备有 (m) 个属性,用向量(z[i]=(a_{i,1},a_{i,2},..,a_{i,m})) 表示,每个装备需要花费 (c_i)

现在脸哥想买一些装备,但是脸哥很穷,所以总是盘算着怎样才能花尽量少的钱买尽量多的装备。

对于脸哥来说,如果一件装备的属性能用购买的其他装备组合出(也就是说脸哥可以利用手上的这些装备组合出这件装备的效果),那么这件装备就没有买的必要了。

严格的定义是,如果脸哥买了 (z[i_1],z[i_2],…,z[i_p]) 这 p 件装备,并且不存在实数 (b_1,b_2,…,b_p) 使得 (z[k]=b_1z[i_1]+b_2z[i_2]+…+b_pz[i_p]),那么脸哥就会买 (z[k]),否则 (z[k]) 对脸哥就是无用的了,自然不必购买。

脸哥想要在买下最多数量的装备的情况下花最少的钱,你能帮他算一下吗?

输入格式

第一行包含两个整数 (n)(m)

接下来 (n) 行,每行 (m) 个数,其中第 (i) 行描述装备 (i) 的各项属性值。

接下来一行 (n) 个数,其中第 (i) 个数表示购买第 (i) 件装备的花费 (c_i)

输出格式

输出占一行,包含两个整数,第一个整数表示能够购买的最多装备数量,第二个整数表示在购买最多数量的装备的情况下的最小花费。

数据范围

(1≤n,m≤500),
(0≤a_{i,j}≤1000)

输入样例:

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

输出样例:

2 2

题解

一个 (n*m) 的矩阵,需要经过构造线性基,并不断往线性基里面添加元素,存在的话进行消除,不存在进行添加。

因为要保证最小,所以添加之前贪心一下进行操作,所谓贪心就是费用从小到大排序。

这个题比较卡精度~~

代码

#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 555;
int b[maxn];
const double eps = 1e-5;
struct node{
    double a[maxn];
    int n;
};
node a[maxn];
bool cmp(node x,node y){
    return x.n<y.n;
}
void Base(int n,int m){
    int ans=0,cnt=0;
    sort(a,a+n,cmp);
    for(int i=0;i<=500;++i)b[i]=-1;
    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            if(fabs(a[i].a[j])<eps)continue;
            if(b[j]!=-1){
                double tmp=a[i].a[j]/a[b[j]].a[j];
                for(int k=j;k<m;++k){
                    a[i].a[k]-=tmp*a[b[j]].a[k];
                }
            }
            else{
                b[j]=i;
                cnt++;
                ans+=a[i].n;
                break;
            }
        }
    }
    printf("%d %d
",cnt,ans);
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i)
        for(int j=0;j<m;++j)
            scanf("%lf",&a[i].a[j]);
    for(int i=0;i<n;++i)
        scanf("%d",&a[i].n);
    Base(n,m);
    return 0;
}
新赛季的开始
原文地址:https://www.cnblogs.com/VagrantAC/p/13253050.html