给出 \(n\) 个 \(m\) 维向量,每个向量都有代价,求 \(n\) 个向量的最大独立集和最小代价.
\(1\leq n,m\leq 500\)
一个向量可以被其他向量表示出来,那么,在高斯消元的矩阵上,消完元之后必定必定没有元素剩下.
而且,对于 \(n\) 个向量来说,插入向量的先后,和最后剩余的个数并没有关系. 每一个维度最终最多只有一个向量为 \(1\) .
那么,考虑从小往大插入向量,那么,可以保证最后能够插入矩阵的向量代价最小.
考虑一个向量 \(i\) 和 \(j\) ,如果插入 \(i\) 会导致无法插入 \(j\) ,那么,插入 \(j\) 也会导致无法插入 \(i\) . 那么,肯定要有限满足 \(i\) 和 \(j\) 里面代价小的一个优先插入.
这个道理和线性基里面用得比较多,以前做过一道类似的题目,是很久之前的wc.
时间复杂度 : \(O(nm^2)\)
空间复杂度 : \(O(nm)\)
第一次提交 : Accepted
code
#include<bits/stdc++.h>
using namespace std;
long double eps=1e-9;
int n,m;
long double a[505][505];
bool ins(vector<long double>v){
cout<<fixed<<setprecision(10);
for(int i=0;i<m;i++){
if(abs(v[i])<eps)continue;
for(int j=m-1;j>=i;j--){
v[j]-=a[i][j]*v[i];
}
}
for(int i=0;i<m;i++){
if(abs(v[i])>eps){
for(int j=m-1;j>=i;j--){
a[i][j]=v[j]/v[i];
}
return true;
}
}
return false;
}
vector<long double>v[505];
vector<pair<int,int> >c;
int ans=0;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int x;
cin>>x;
v[i].push_back(x);
}
}
for(int i=0;i<n;i++){
int cost;
cin>>cost;
c.push_back(make_pair(cost,i));
}
sort(c.begin(),c.end());
int sum=0;
for(int i=0;i<(int)c.size();i++){
int id=c[i].second;
if(ins(v[id])){
sum++;
ans+=c[i].first;
}
}
cout<<sum<<" "<<ans<<endl;
return 0;
}
/*inline? ll or int? size? min max?*/