链接
https://www.luogu.org/problemnew/show/P3265
题解
这题其实就是找一组基向量,而且权值和最小
先把所有的向量按照权值升序排序,然后从上往下依次检查看能否加入基向量集合就好了
代码
#include <bits/stdc++.h>
#define maxn 510
#define eps 1e-5
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
int N, M;
struct LinearBasis
{
double mat[maxn][maxn];
bool ok[maxn];
void clear(){cl(mat);}
void insert(double* v)
{
for(auto i=1;i<=M;i++)
{
if(fabs(v[i])>eps)
{
if(!ok[i])
{
for(auto j=1;j<=M;j++)mat[i][j]=v[j];
ok[i]=true;
break;
}
else
{
for(auto j=M;j>=i;j--)v[j]-=v[i]/mat[i][i]*mat[i][j];
}
}
}
}
bool check(double* v)
{
for(auto i=1;i<=M;i++)
{
if(ok[i] and fabs(v[i])>eps)
{
for(auto j=M;j>=i;j--)v[j]-=v[i]/mat[i][i]*mat[i][j];
}
}
for(auto i=1;i<=M;i++)if(fabs(v[i])>eps)return false;
return true;
}
}LB;
int num[maxn], c[maxn], ans, cnt;
double mat[maxn][maxn];
int main()
{
ios::sync_with_stdio(false);
int i, j;
cin>>N>>M;
for(i=1;i<=N;i++)for(j=1;j<=M;j++)cin>>mat[i][j];
for(i=1;i<=N;i++)cin>>c[i], num[i]=i;
sort(num+1,num+N+1,[](int a, int b)->bool{return c[a]<c[b];});
for(i=1;i<=N;i++)
{
if(!LB.check(mat[num[i]]))LB.insert(mat[num[i]]), ans+=c[num[i]], cnt++;
}
cout<<cnt<<' '<<ans;
return 0;
}