[JLOI2015]装备购买,洛谷P3265,实数线性基

版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/83756630

正题

      题目链接

      回想线性基的过程,是不是碰到第i位有数,就必须把第i位清空?

      其实这个就是一个高斯消元的过程,只不过他少了未知数。

      这题当然也可以用高斯消元做,看一下当前这个能不能被前面的构造出来,这样的复杂度会显得很高。

      思考运用线性基的性质。

      第i位为1。第i个数下面的数的第i位肯定为0.

      那么现在线性基存的就是一个向量,每次遇到第x位不为0,而且线性基中这里有向量,那就把向量减去线性基中的向量乘上一个数。(初等变换)

      然后如果没有向量就存进去。

      到最后如果可以被线性基中的向量组合出来,那么这个装备(向量)就没必要买。

      从小到大放,不能放的就丢掉,得到的一定是最小的数,而且可以证明取的装备一定是最大的(别问我,要问我的感性

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

struct node{
	double a[510];
	int d;
	bool operator<(const node x)const{
		return d<x.d;
	}
}s[510];
int n,m;
double p[510][510];
bool tf[510];
double eps=1e-5;

bool insert(node x){
	bool we=false;
	for(int i=m;i>=1;i--)
		if(fabs(x.a[i])>eps){
			if(tf[i]) for(int j=1;j<=i;j++) x.a[j]-=p[i][j]*x.a[i]/p[i][i];
			else{
				for(int j=i;j>=1;j--) p[i][j]=x.a[j];
				we=true;tf[i]=true;
				break;
			}
		}
	return we;
}

int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=m;j>=1;j--)
			scanf("%lf",&s[i].a[j]);
	for(int i=1;i<=n;i++) scanf("%d",&s[i].d);
	sort(s+1,s+1+n);
	int ans=0,t=0;
	for(int i=1;i<=n;i++) if(insert(s[i])) ans+=s[i].d,t++;
	printf("%d %d\n",t,ans);
}

猜你喜欢

转载自blog.csdn.net/Deep_Kevin/article/details/83756630