[JLOI2015]装备购买

<body> <center><h1>4004: [JLOI2015]装备购买</h1><span class="green">Time Limit: </span>20 Sec&nbsp;&nbsp;<span class="green">Memory Limit: </span>128 MB<br><span class="green">Submit: </span>2486&nbsp;&nbsp;<span class="green">Solved: </span>773<br>[<a href="submitpage.php?id=4004">Submit</a>][<a href="problemstatus.php?id=4004">Status</a>][<a href="bbs.php?id=4004">Discuss</a>]</center> <h2>Description</h2> <div class="content"> 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 &lt;= i &lt;= n; 1 &lt;= j &lt;= m),每个装备需要花费 ci,现在脸哥想买一些装备,但是脸哥很穷,所以总是盘算着 怎样才能花尽量少的钱买尽量多的装备。对于脸哥来说,如果一件装备的属性能用购买的其他装备组合出(也就是 说脸哥可以利用手上的这些装备组合出这件装备的效果),那么这件装备就没有买的必要了。严格的定义是,如果 脸哥买了 zi1,.....zip这 p 件装备,那么对于任意待决定的 zh,不存在 b1,....,bp 使得 b1zi1 + ... + bpzi p = zh(b 是实数),那么脸哥就会买 zh,否则 zh 对脸哥就是无用的了,自然不必购买。举个例子,z1 =(1; 2; &nbsp;3);z2 =(3; 4; 5);zh =(2; 3; 4),b1 =1/2,b2 =1/2,就有 b1z1 + b2z2 = zh,那么如果脸哥买了 z1 和 z2&nbsp; 就不会再买 zh 了。脸哥想要在买下最多数量的装备的情况下花最少的钱,你能帮他算一下吗? </div> <h2>Input</h2> <div class="content"> 第一行两个数 n;m。接下来 n 行,每行 m 个数,其中第 i 行描述装备 i 的各项属性值。接下来一行 n 个数, 其中 ci 表示购买第 i 件装备的花费。 </div> <h2>Output</h2> <div class="content">一行两个数,第一个数表示能够购买的最多装备数量,第二个数表示在购买最多数量的装备的情况下的最小花费 </div> <h2>Sample Input</h2> <div class="content"> <span class="sampledata"> 3 3<br> 1 2 3<br> 3 4 5<br> 2 3 4<br> 1 1 2 </span> </div> <h2>Sample Output</h2> <div class="content"> <span class="sampledata"> 2 2</span> </div> <h2>HINT</h2> <div class="content"><p></p><div>如题目中描述,选择装备 1 装备 2,装备 1 装备 3,装备 2 装备 3 均可,但选择装备 1 和装备 2 的花费最小,为 2。对于 100% 的数据, 1 &lt;= n;m &lt;= 500; 0 &lt;= aj &lt;= 1000。</div><br> <div>新加数据三组--2016.5.13</div><br> <div></div><br> <div></div><br> <div></div><p></p></div><h2>Source</h2> <div class="content"><p><a href="problemset.php?search="></a></p></div><center>[<a href="submitpage.php?id=4004">Submit</a>][<a href="problemstatus.php?id=4004">Status</a>][<a href="bbs.php?id=4004">Discuss</a>]</center><br> <a href="./"><span class="red">HOME</span></a> <a href="javascript:history.go(-1)"><span class="red">Back</span></a> </body>

题解

装备无用就是线性相关,那么此题要求的就是极大无关线性子集,若把a表示成矩阵,就是求矩阵的秩,高斯消元即可。

要求花费最少,那么考虑每个主元的时候,找到该主元不为0的花费最少的向量即可。

时间复杂度\(O(N^3)\)

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long ll;

long double a[510][510],eps=1e-8;
int c[510],n,m,dim,ans;
int main()
{
//	freopen(".in","r",stdin),freopen(".out","w",stdout);
	read(n),read(m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j) read(a[i][j]);
	for(int i=1;i<=n;++i) read(c[i]);
	for(int i=1;i<=m;++i){
		int now=0;
		for(int j=dim+1;j<=n;++j)
			if(fabs(a[j][i])>eps&&(now==0||c[j]<c[now])) now=j;
		if(now==0) continue;
		++dim,ans+=c[now];
		std::swap(a[now],a[dim]),std::swap(c[now],c[dim]);
		for(int j=1;j<=n;++j) if(dim!=j&&fabs(a[j][i])>eps){
			long double rate=a[j][i]/a[dim][i];
			for(int k=i;k<=m;++k)
				a[j][k]-=a[dim][k]*rate;
		}
	}
	printf("%d %d\n",dim,ans);
	return 0;
}

posted on 2019-03-03 15:35  autoint  阅读(152)  评论(0)    收藏  举报

导航