题目描述
脸哥最近在玩一款神奇的游戏,这个游戏里有
对于脸哥来说,如果一件装备的属性能用购买的其他装备组合出(也就是说脸哥可以利用手上的这些装备组合出这件装备的效果),那么这件装备就没有买的必要了。严格的定义是,如果脸哥买了
举个例子,
输入输出格式
输入格式:
第一行两个数
输出格式:
一行两个数,第一个数表示能够购买的最多装备数量,第二个数表示在购买最多数量的装备的情况下的最小花费
输入输出样例
输入样例#1:
3 3
1 2 3
3 4 5
2 3 4
1 1 2
输出样例#1:
2 2
说明
如题目中描述,选择装备
对于
题解
题意:给定
首先我们不考虑权值的问题。
求一个
举个栗子(样例):
其中最终的行阶梯型矩阵的秩
接下来我们在来考虑权值的问题。由于矩阵进行初等行变换秩不变,我们可以贪心得从小到大加入矩阵,然后尽量用权值低的向量消掉权值高的向量即可。
在这里我用的类似线性基维护。
复杂度
My Code
本题卡精度,所以使用 long double,并开大eps
否则你会这样:
/**************************************************************
Problem: 4004
User: infinityedge
Language: C++
Result: Accepted
Time:1372 ms
Memory:7908 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define eps 1e-6
using namespace std;
struct vec{
long double d[501];
int c;
}v[505];
int cmp(vec x, vec y){
return x.c < y.c;
}
long double b[501][501];
int n, m;
int ans[501], vis[501];
void solve(){
for(int i = 1; i <= n; i ++){
for(int j = m; j >= 1; j --){
if(fabs(v[i].d[j]) > eps){
if(fabs(b[j][j]) > eps){
long double dk = v[i].d[j] / b[j][j];
for(int k = 1; k <= m; k ++){
v[i].d[k] -= b[j][k] * dk;
}
}else{
for(int k = 1; k <= m; k ++){
b[j][k] = v[i].d[k];
}
ans[j] = v[i].c;
vis[j] = 1;
break;
}
}
}
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= m; j ++){
scanf("%Lf", &v[i].d[j]);
}
}
for(int i = 1; i <= n; i ++){
scanf("%d", &v[i].c);
}
sort(v + 1, v + n + 1, cmp);
solve();
int pans = 0, cnt = 0;
for(int i = 1; i <= m; i ++){
if(vis[i]) cnt++, pans += ans[i];
}
printf("%d %d\n", cnt, pans);
return 0;
}