1 //Guass_未测试版本 2 /* 3 如果可以肯定有唯一解,可以用化成上三角,时间有一点优势;但是如果存在自由变量 4 那么就不能这么写,而且化成上三角后,对应的行号和列号会发生错位; 5 6 */ 7 const double eps=1e-10; 8 typedef double Matrix[N][N]; 9 void gauss(Matrix A,int n){ //n个方程组,n个自由变量;A[i][n]放常量y[i]; 10 int i,j,r,c,id; 11 for (r=0;r<n;r++){ 12 id=r; 13 for (i=r+1;i<n;i++) if (fabs(A[id][r])<fabs(A[i][r])) id=i; 14 if (id!=r) for (j=r;j<=n;j++) swap(A[id][j],A[r][j]); 15 16 for (i=r+1;i<n;i++){ 17 double tmp=A[i][r]/A[r][r]; 18 for (j=r;j<=n;j++){ 19 A[i][j]-=tmp*A[r][j]; 20 } 21 } 22 } 23 //在A[i][n]放x[i]; 24 for (i=n-1;i>=0;i--){ 25 for (j=n-1;j>i;j--){ 26 A[i][n]-=A[i][j]*A[j][n]; 27 } 28 A[i][n]/=A[i][i]; 29 } 30 } 31 /* 32 化成斜线方程,可以避免行号和列号发生错位,但时间会稍慢一点, 33 而且当方程组有解时,唯一解:x[i]=A[i][n]/A[i][i] 34 无穷多解,A[i][n]/A[i][i]表示在自由变量取0时的x[i]; 35 */ 36 int gauss_jordan(Matrix A,int n){ 37 int i,j,r,c,id; 38 for (r=0;r<n;r++){ 39 id=r; 40 for (i=r+1;i<n;i++) if (fabs(A[id][r])<fabs(A[i][r])) id=i; 41 if (fabs(A[id][r])<eps) continue; 42 43 for (i=0;i<n;i++){ 44 if (i==r) continue; 45 double f=A[i][r]/A[r][r]; 46 for (j=r+1;j<=n;j++){ 47 A[i][j]-=f*A[i][j]; 48 } 49 } 50 } 51 int cnt=0; 52 for (i=0;i<n;i++){ 53 if (fabs(A[i][i])<eps && fabs(A[i][n])>eps) return -1;//无解; 54 if (fabs(A[i][i])<eps && fabs(A[i][n])<eps) cnt++;//自由变量; 55 } 56 if (cnt==0) return 0;//唯一解; 57 return cnt;//自由元的数量; 58 } 59 //提高精度版本;行列变换用它们的最小公倍数,所以只在最后求解的时候除法; 60 //注意数据会不会越界; 61 int gauss_jordan(Matrix A,int n){ 62 int i,j,r,c,id; 63 for (r=0;r<n;r++){ 64 id=r; 65 for (i=r+1;i<n;i++) if (abs(A[id][r])<abs(A[i][r])) id=i; 66 if (abs(A[id][r])==0) continue; 67 68 for (i=0;i<n;i++){ 69 if (i==r) continue; 70 int g=__gcd(A[r][r],A[i][r]); 71 int tp1=A[r][r]/g,tp2=A[i][r]/g; 72 for (j=r;j<=n;j++){ 73 A[i][j]=A[i][j]*tp1-A[r][j]*tp2; 74 } 75 } 76 } 77 int cnt=0; 78 for (i=0;i<n;i++){ 79 if (abs(A[i][i])==0 && abs(A[i][n])>0) return -1;//无解; 80 if (abs(A[i][i])==0 && abs(A[i][n])==0) cnt++;//自由变量; 81 } 82 if (cnt==0) return 0;//唯一解; 83 return cnt;//自由元的数量; 84 } 85 86 87 /*二进制的gauss*/ 88 int gauss(Matrix A,int n,int m){ 89 int i,j,r,c,id; 90 for (r=0,c=0;r<n && c<m;r++,c++){ 91 92 for (i=r;i<n;i++) if (A[i][c]) { id=i;break; } 93 if (A[id][c])==0){ r--;continue; } 94 if (id!=r) for (j=c;j<=m;j++) swap(A[id][j],A[r][j]); 95 96 for (i=r+1;i<n;i++)if (A[i][c]){ 97 for (j=c;j<=m;j++) A[i][j]^=A[r][j]; 98 } 99 } 100 for (i=r;i<n;i++) if (abs(A[i][n])>0) return -1;//无解; 101 if (m-r>0) return m-r;//自由元的个数; 102 103 }
hust 1651 **
1 /* 2 题意:n*m的矩阵,要么是非负整数,要么是-1,-1表示要填的数, 3 然后告诉你每一行,每一列的和,问你有无解,每行每列至多2个-1; 4 5 很简单的想法就是列出n+m个方程组然后gauss,但gauss给我们的印象就是o(n^3; 6 所以也许就把这个想法抛弃了,但实际是每个未知数最多出现在两个方程里,也就是 7 在行里变换中,只需要变换一行后就可以直接break,时间复杂度就是O(n^2); 8 9 */ 10 #include<iostream> 11 #include<cmath> 12 #include<vector> 13 #include<algorithm> 14 #include<cstdio> 15 #include<cstdlib> 16 #include<cstring> 17 using namespace std; 18 const int N=1000+10; 19 typedef double Matrix[N][N]; 20 int mz[N][N],c[N][N]; 21 int a[N],b[N]; 22 int n,m,sz; 23 const double eps=1e-10; 24 Matrix A; 25 int gauss(Matrix A,int n,int m){ 26 int i,j,r,c,id; 27 for (r=0,c=0;r<n && c<m;r++,c++){ 28 id=r; 29 for (i=r;i<n;i++) if (fabs(A[i][c])>fabs(A[id][c])) id=i; 30 if (fabs(A[id][c])<eps) { r--;continue; } 31 if (id!=r) for (j=c;j<=m;j++) swap(A[id][j],A[r][j]); 32 33 for (i=r+1;i<n;i++){ 34 if (A[i][c]==0) continue; 35 double f=A[i][c]/A[r][c]; 36 for (j=c;j<=m;j++){ 37 A[i][j]-=f*A[r][j]; 38 } 39 break; 40 } 41 } 42 for (i=r;i<n;i++) if (abs(A[i][m])>0) return -1; 43 if (m-r>0) return 2; 44 return 1; 45 } 46 void work(){ 47 memset(A,0,sizeof(A)); 48 for (int i=0;i<n;i++){ 49 int sum=0; 50 for (int j=0;j<m;j++){ 51 if (c[i][j]!=-1) A[i][c[i][j]]=1; 52 sum+=mz[i][j]; 53 } 54 A[i][sz]=a[i]-sum; 55 } 56 for (int j=0;j<m;j++){ 57 int sum=0; 58 for (int i=0;i<n;i++){ 59 if (c[i][j]!=-1) A[j+n][c[i][j]]=1; 60 sum+=mz[i][j]; 61 } 62 A[n+j][sz]=b[j]-sum; 63 } 64 /* cout<<"++++ "<<endl; 65 for (int i=0;i<n+m;i++){ 66 for (int j=0;j<=sz;j++){ 67 cout<<A[i][j]<<" "; 68 }cout<<endl; 69 } 70 cout<<"+++++ "<<endl; 71 */int t=gauss(A,n+m,sz); 72 if (t==-1) printf("No solution\n"); 73 else if (t==1) printf("Unique\n"); 74 else printf("More than one\n"); 75 } 76 int main(){ 77 int T,cas=0; 78 scanf("%d",&T); 79 while (T--){ 80 scanf("%d%d",&n,&m); 81 sz=0; 82 memset(c,-1,sizeof(c)); 83 for (int i=0;i<n;i++){ 84 for (int j=0;j<m;j++){ 85 scanf("%d",&mz[i][j]); 86 if (mz[i][j]==-1){ 87 mz[i][j]=0; 88 c[i][j]=sz++; 89 } 90 } 91 } 92 for (int i=0;i<n;i++) scanf("%d",&a[i]); 93 for (int j=0;j<m;j++) scanf("%d",&b[j]); 94 printf("Case #%d: ",++cas); 95 work(); 96 97 98 } 99 100 return 0; 101 } 102 /* 103 5 104 2 2 105 1 1 106 -1 -1 107 2 4 108 3 3 109 2 2 110 1 1 111 -1 -1 112 2 5 113 3 3 114 2 2 115 1 1 116 2 2 117 2 4 118 3 3 119 4 4 120 1 2 3 4 121 1 -1 -1 2 122 3 -1 -1 4 123 5 6 7 8 124 10 6 14 26 125 10 13 15 18 126 2 2 127 1 -1 128 2 -1 129 -1 1 130 3 -3 131 132 */