Luogu 3265 [JLOI2015]装备购买
BZOJ 4004
把所有不能相互表示出来的向量都买下,一定能得到最大能买的方案数。
求解线性无关向量可以高斯消元,最后没有变成$0$向量的就是基底。
本题还要求代价最小怎么办?我们只要先把所有向量按照代价从小到大排个序然后贪心地选取可行解去消元就可以了。
时间复杂度$O(n^3)$。
要注意精度。
Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long double db; const int N = 505; const db eps = 1e-8; int n, m, used[N]; struct Item { int c; db s[N]; friend bool operator < (const Item &x, const Item &y) { return x.c < y.c; } } a[N]; inline db fabs(db x) { return x > 0 ? x : -x; } int main() { freopen("2.in", "r", stdin); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%Lf", &a[i].s[j]); for(int i = 1; i <= n; i++) scanf("%d", &a[i].c); sort(a + 1, a + 1 + n); int cnt = 0, ans = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { if(fabs(a[i].s[j]) > eps) { if(!used[j]) { used[j] = i, cnt++, ans += a[i].c; break; } else { db f = a[i].s[j] / a[used[j]].s[j]; for(int k = j; k <= m; k++) a[i].s[k] -= f * a[used[j]].s[k]; } } } } printf("%d %d\n", cnt, ans); return 0; }