装备购买
脸哥最近在玩一款神奇的游戏,这个游戏里有 (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;
}