#include<bits/stdc++.h>
using namespace std;
inline int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
long double eps=1e-8,a[505][505];
int tot,ans,val[505];
int main(){
int n=read(),m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]=read()*1.0;
for(int i=1;i<=n;i++)val[i]=read();
for(int i=1;i<=n;i++){
int now=0;
for(int j=tot+1;j<=n;j++)
if((fabs(a[j][i])>eps)&&(now==0||val[j]<val[now]))now=j;
//找到当前最小花费的装备
if(now==0)continue;
//如果它已经被消为了0,则不买它,直接跳过
tot++;ans+=val[now];
//否则,tot记录买的装备个数,ans记录花费
for(int j=1;j<=m;j++)swap(a[now][j],a[tot][j]);
swap(val[now],val[tot]);
//把当前买的这一行装备交换到第tot行
//这里实际上使得前tot行都是确定要买的装备
//所以之后的枚举中可以不考虑它们了
for(int j=tot+1;j<=n;j++){
if(fabs(a[j][i])>eps){
long double cnt=a[j][i]*1.0/a[tot][i];
for(int k=i;k<=m;k++)a[j][k]-=cnt*a[tot][k];
}
}
//用当前买的这件装备去消其它装备
}
printf("%d %d\n",tot,ans);
return 0;
}
原文:https://www.cnblogs.com/PPXppx/p/10628215.html