【数学 线性基】AcWing 209. 装备购买
传送门:
https://www.acwing.com/problem/content/description/211/
分析
采取这样的贪心策略:将物品看作是矩阵中的行,按照花费升序排序,然后从 扫描,当第 个行和前面加入的所有行线性无关的时候,就将其花费计入答案,反之不计入。
这样做为什么是对的呢?采用归纳法来证明:
下证:前 行采取上述策略能够在保证选出的行构成的线性空间与前 行构成的线性空间相等的前提下花费最小。
- 前 行,我们肯定需要将第一行加入贡献,满足。
- 假设前 行满足上述贪心策略。
- 下只需证明前 行采取上述贪心策略是最优的。
- 如果前 行构成的线性空间和前 行构成的线性空间相等(也就是第 行能被前 行选出的行线性表出),那么我们肯定不选取,满足最优。
- 如果不相等,也就是第 行与前 行线性无关。假设我们不选取第 行,那么无论如何从前 行进行选取也不能使得选出的行构成的线性空间与前 行构成的线性空间相等,因此必须选。
实现
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
const int N=550;
const double eps=1e-5;
int n, m;
int w[N][N], c[N];
int idx[N];
bool zero(double x){
return abs(x)<eps;
}
bool zero(vector<double> a){
for(auto i: a) if(!zero(i)) return false;
return true;
}
void change(vector<double> &a, vector<double> &b){
rep(i,0,m-1){
if(zero(a[i]) && !zero(b[i])) return;
if(!zero(a[i]) && zero(b[i])){
swap(a, b);
return;
}
if(!zero(a[i]) && !zero(b[i])){
double rate=a[i]/b[i];
rep(j,i,m-1) a[j]-=rate*b[j];
return;
}
}
}
int main(){
cin>>n>>m;
rep(i,1,n) rep(j,1,m) read(w[i][j]);
rep(i,1,n) read(c[i]);
rep(i,1,n) idx[i]=i;
sort(idx+1, idx+1+n, [](int x, int y){
return c[x]<c[y];
});
vector<vector<double>> a;
ll res=0;
rep(i,1,n){
int p=idx[i];
vector<double> row;
rep(j,1,m) row.pb(w[p][j]);
for(auto &vec: a) change(row, vec);
if(!zero(row)) a.pb(row), res+=c[p];
}
cout<<a.size()<<' '<<res<<endl;
return 0;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】