#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef double DB;
typedef unsigned long long ULL;
typedef unsigned int Uint;
const int INT_INF=0x3fffffff;
const LL LL_INF=0x3fffffffffffffff;
const DB EPS=1e-9;
const DB PI=3.14159265358979323846;
const int N=10010;
const int E=10010;
#define PB push_back
#define MP make_pair
#define MH make_heap
#define PH push
int A[N][N];
int Up[N], Down[N]; //Up 存储的是分子, Down存储的是分母
bool Free[N];
int equation, variable;
void debug()
{
printf("The Matrix is :\n");
for(int i=0; i<=variable+1; i++)
{
printf("%4d",i);
if(i==0) printf("|");
}
printf("\n");
for(int i=0; i<=variable+1; i++)
{
printf("---");
if(i==0) printf("-+");
else printf("-");
}
printf("\n");
for(int i=1; i<=equation; i++)
{
printf("%4d|",i);
for(int j=1; j<=variable+1; j++)
{
printf("%4d",A[i][j]);
}
printf("\n");
}
printf("\n");
}
/***************************************************************************/
/* 功能说明:
/* 1、不需带入参数,参数已经在 build() 函数中设置好了
/* 2、函数返回 -1 :无解
/* 3、函数返回 0 :有且仅有一组解
/* 4、函数返回 其他正数 :有多解,返回的值是不确定变元的个数
/**************************************************************************/
int gauss()
{
int col=1, row=1;
for(; row<=equation && col<=variable; row++, col++)
{
int max_row=row;
//找到 col 那列元素绝对值最大的那行与当前行交换,减小精度误差
for(int i=row+1; i<=equation; i++)
if(abs(A[i][col])>abs(A[max_row][col]))
max_row=i;
//如果 col 那列元素最大是 0,表明这一列全部是 0,处理下一列
if(A[max_row][col]==0)
{
row--;
continue;
}
//如果不是同一行,交换元素
if(max_row!=row)
{
for(int i=col; i<=variable+1; i++)
swap(A[max_row][i], A[row][i]);
}
//枚举要删去的行
//for(int i=row+1; i<=equation; i++)
for(int i=1; i<=equation; i++)
{
if(i==row) continue;
if(A[i][col]==0) continue;
int GCD=__gcd(abs(A[i][col]), abs(A[row][col]));
int ta=abs(A[row][col]) / GCD;
int tb=abs(A[i][col]) / GCD;
// printf("ta=%d tb=%d\n",ta,tb);
//如果异号,应该相加
if((A[i][col]>0 && A[row][col]<0) || (A[i][col]<0 && A[row][col]>0)) tb=-tb;
//对于 j 的起点问题,如果我是只把当前行后面的行的元素消掉,我可以是从 col 开始,
//但如果是从第一行开始消掉,必须从 1 开始
for(int j=1; j<=variable+1; j++)
A[i][j]=A[i][j]*ta-A[row][j]*tb;
//A[i][j]-=A[row][j]*tb/ta;
}
// printf("row=%d col=%d\n", row, col);
// debug();
}
// debug();
// 1、没有解的情况:
for(int i=row; i<=equation; i++)
if(A[i][variable+1]!=0) return -1; //表明无解
// 2、无穷解的情况:
if(row<variable+1)
{
for(int i=row-1; i>=1; i--)
{
int free_x_num=0, free_index=-1;
for(int j=1; j<=variable; j++)
if(Free[j] && A[i][j]!=0)
{
free_x_num++;
free_index=j;
}
if(free_x_num>1) continue;
Free[free_index]=false;
int Up_temp=A[i][variable+1];
int Down_temp=1;
for(int j=1; j<=variable; j++)
if(A[i][j]!=0 && j!=free_index)
{
int GCD=__gcd(abs(Down[j]), abs(A[i][j]));
int U=Up[j]*A[i][j]/GCD;
int D=Down[j]/GCD;
GCD=__gcd(abs(D), abs(Down_temp));
int ta=D/GCD;
int tb=Down_temp/GCD;
Up_temp=Up_temp*ta-U*tb;
Down_temp*=ta;
GCD=__gcd(abs(Up_temp), abs(Down_temp));
Up_temp/=GCD;
Down_temp/=GCD;
}
if(Up_temp==0)
{
Up[free_index]=0;
continue;
}
int GCD=__gcd(abs(Up_temp), abs(A[i][free_index]));
Down[free_index]=A[i][free_index]/GCD*Down_temp;
Up[free_index]=Up_temp/GCD;
}
return variable-row+1;
}
// 3、唯一解的情况:
for(int i=variable; i>=1; i--)
{
int Up_temp=A[i][variable+1];
int Down_temp=1;
for(int j=i+1; j<=variable; j++)
if(A[i][j]!=0)
{
int GCD=__gcd(abs(Down[j]), abs(A[i][j]));
int U=Up[j]*A[i][j]/GCD;
int D=Down[j]/GCD;
GCD=__gcd(abs(D), abs(Down_temp));
int ta=D/GCD;
int tb=Down_temp/GCD;
Up_temp=Up_temp*ta-U*tb;
Down_temp*=ta;
GCD=__gcd(abs(Up_temp), abs(Down_temp));
Up_temp/=GCD;
Down_temp/=GCD;
}
if(Up_temp==0)
{
Up[i]=0;
continue;
}
int GCD=__gcd(abs(Up_temp), abs(A[i][i]));
Down[i]=A[i][i]/GCD*Down_temp;
Up[i]=Up_temp/GCD;
}
return 0;
}
void build(int n, int m)
{
memset(Free, true, sizeof(Free));
memset(Up, 0, sizeof(Up));
for(int i=0; i<N; i++)
Down[i]=1;
variable=n, equation=m;
for(int i=1; i<=equation; i++)
for(int j=1; j<=variable+1; j++)
scanf("%d",&A[i][j]);
debug();
}
void PRINT(int flag)
{
if(flag==-1)
{
printf("NO Solution !\n");
return;
}
if(flag==0)
{
for(int i=1; i<=variable; i++)
printf("x%d : %d/%d\n", i, Up[i], Down[i]);
return;
}
printf("There are %d variables who are indeterminate !\n",flag);
for(int i=1; i<=variable; i++)
{
printf("x%d : ", i);
if(Free[i]) printf("indeterminate !\n");
else printf("%d/%d\n",Up[i], Down[i]);
}
}
int main()
{
freopen("C:/Users/zhj5chengfeng/Desktop/in.txt","r",stdin);
freopen("C:/Users/zhj5chengfeng/Desktop/out.txt","w",stdout);
int ca=0;
while(~scanf("%d%d", &variable, &equation))
{
printf("Case #%d :\n", ++ca);
build(variable, equation);
PRINT(gauss());
printf("\n\n\n\n");
}
return 0;
}
/*
Input:
4 3
1 -2 1 5 3
1 -2 4 -34 0
2 -4 3 -3 5
2 2
1 2 27
2 1 0
3 3
3 -1 5 3
1 -1 2 1
1 -2 -1 2
Output:
Case #1 :
The Matrix is :
0| 1 2 3 4 5
----+--------------------
1| 1 -2 1 5 3
2| 1 -2 4 -34 0
3| 2 -4 3 -3 5
There are 2 variables who are indeterminate !
x1 : indeterminate !
x2 : indeterminate !
x3 : indeterminate !
x4 : indeterminate !
Case #2 :
The Matrix is :
0| 1 2 3
----+------------
1| 1 2 27
2| 2 1 0
x1 : -9/1
x2 : 18/1
Case #3 :
The Matrix is :
0| 1 2 3 4
----+----------------
1| 3 -1 5 3
2| 1 -1 2 1
3| 1 -2 -1 2
x1 : 10/7
x2 : 1/-7
x3 : -2/7
*/
高斯消元模板——整数参数型
最新推荐文章于 2018-07-20 19:40:37 发布