版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/86295368
思路分析:
考虑求解所有n个装备的属性对应的n个长度为m的向量的基底, 使用高斯消元时, 每次选择当前对应列非零, 且价格最低的行(装备)进行消元, 具体实现如下AC代码所示:
//BZOJ4004_装备购买
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAX = 1e3, INF = 0x3f3f3f3f;
const long double eps = 1e-8;
long double a[MAX][MAX]; int c[MAX], n, m;
int main(){
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j) cin >> a[i][j];
for(int i = 1; i <= n; ++i) scanf("%d", &c[i]);
int dim = 0;
for(int i = 1; i <= m; ++i){
for(int j = dim + 1; j <= n; ++j)
if(abs(a[j][i]) > eps
&& (abs(a[dim + 1][i]) < eps || c[j] < c[dim + 1])){
for(int k = 1; k <= m; ++k) swap(a[dim + 1][k], a[j][k]);
swap(c[dim + 1], c[j]);
}
if(abs(a[dim + 1][i]) < eps) continue;
for(int j = 1; j <= n; ++j){
if(j == dim + 1) continue;
if(abs(a[j][i]) > eps){
long double rate = a[j][i] / a[dim + 1][i];
for(int k = 1; k <= m; ++k) a[j][k] -= a[dim + 1][k] * rate;
}
}
++dim;
}
int cnt = 0, val = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(abs(a[i][j]) > eps){
++cnt, val += c[i];
break;
}
cout << cnt << " " << val << endl;
return 0;
}