• 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;
    }
    
    新赛季的开始
  • 相关阅读:
    艾伟_转载:基于.NET平台的Windows编程实战(三)—— 项目的创建及主界面的设计 狼人:
    艾伟_转载:C# Design Patterns (2) Strategy 狼人:
    艾伟_转载:C# Design Patterns (5) Prototype 狼人:
    艾伟_转载:正则表达式30分钟入门教程 狼人:
    艾伟_转载:WCF安全之EndPointIdentity 狼人:
    艾伟_转载:老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现 狼人:
    艾伟_转载:.NET平台上的Memcached客户端介绍 狼人:
    艾伟_转载:关于.NET中的循环引用 狼人:
    艾伟_转载:VS 2008快捷键 狼人:
    艾伟_转载:Regex.Replace 方法的性能! 狼人:
  • 原文地址:https://www.cnblogs.com/VagrantAC/p/13253050.html
Copyright © 2020-2023  润新知