[JLOI2015]装备购买

给出 \(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?*/

上一篇:linux虚拟环境和pip命令


下一篇:D. 505(状压dp)