题目链接:https://vjudge.net/problem/Gym-100962A
题目大意:
给出一个 \(h \times w\) 的目标矩阵。定义一种 \(h \times w\) 的矩阵,它由两个向量 \(a = (a_1, a_2, ..., a_h)\) 和 \(b = (b_1, b_2, ..., b_w)\) 推出,其第 \(i\) 行第 \(j\) 列的元素为 \(a_i b_j\),问目标矩阵最少由多少个这种矩阵相加而成(一开始是零矩阵)。
知识点: 高斯消元
解题思路:
其实就是求 \(h\) 的方程、\(w\) 个未知数的方程组的秩。不过这题的坑点在于精度。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 200+5; 5 const double ep = 1e-2; //一开始是 1e-6, 一直wa, 后来看了题解, 学他改成 1e-2 就 AC 了 6 double a[maxn][maxn]; 7 8 int Gauss(int equ,int var){ 9 int row=0,col=0,max_r; 10 for(;row<equ&&col<var;row++,col++){ 11 max_r=row; 12 for(int i=row+1;i<equ;i++){ 13 if(fabs(a[i][col])>fabs(a[max_r][col])) 14 max_r=i; 15 } 16 if(max_r!=row){ 17 for(int j=row;j<var+1;j++) 18 swap(a[row][j],a[max_r][j]); 19 } 20 if(fabs(a[row][col])<ep){ 21 row--; 22 continue; 23 } 24 for(int i=row+1;i<equ;i++){ 25 if(fabs(a[i][col])>ep){ 26 double f=a[i][col]/a[row][col]; 27 for(int j=row;j<=var;j++){ 28 a[i][j]-=f*a[row][j]; 29 } 30 } 31 } 32 } 33 return row; 34 } 35 int main(){ 36 // freopen("in.txt","r",stdin); 37 int h,w; 38 while(scanf("%d%d",&h,&w)==2){ 39 memset(a,0,sizeof(a)); 40 for(int i=0;i<h;i++){ 41 for(int j=0;j<w;j++) 42 scanf("%lf",&a[i][j]); 43 a[i][w]=0; 44 } 45 printf("%d\n",Gauss(h,w)); 46 } 47 return 0; 48 }