裝備購買
哈哈,這纔是真正的線性基呀!跟線性代數裏面學的一模一樣!
題意:
求給定矩陣的秩,並且所選的基底儘可能小(“小”的定義在題面中)
思路:
- 像平時做的二進制線性基一樣插入即可
- 插入前按照的值先排個序,就當做貪心了吧
- (補充:如果所有條件全部換成整數,而不是實數,則不能當做線性基處理。比如將此處的維換成維,那麼這個問題就變成揹包問題了,比如貨幣系統)
題面描述
#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}
const int maxn = 5e2+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-6; //這裏改成1e-10反而WA了兩個點!!!
struct P{
long double mat[maxn];
int c;
long double & operator [] (const int x) { return mat[x]; }
friend bool operator < (const P &a, const P &b) { return a.c<b.c; }
}a[maxn];
int n, m, cnt, ans, p[maxn];
int main() {
//ios::sync_with_stdio(false); cin.tie(0);
n=read(), m=read();
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j) scanf("%Lf", &a[i][j]);
for(int i=1; i<=n; ++i) a[i].c=read();
sort(a+1,a+1+n);
for(int i=1; i<=n; ++i) {
for(int j=1; j<=m; ++j) if(fabs(a[i][j])>eps) {
if(!p[j]) { cnt++, ans+=a[i].c, p[j]=i; break; }
long double t=a[i][j]/a[p[j]][j];
for(int k=j; k<=m; ++k) a[i][k]-=t*a[p[j]][k];
}
}
printf("%d %d\n", cnt, ans);
}