高斯消元法(约当消元法)

这个真的烦了我好久啊,可能是我太笨了,最后看了几个模板,和写了好久,终于让我弄懂了.具体看代码咯
这个是直接判断是否为0的,精度几乎没有.

#include
#include
#include
#include
#include
using namespace std;
double a[128][128];
int m,n;
int cmp(double x, double y)
{
    double v=fabs(x-y);
    if(v>1e-6)  return 1;
    else return 0;
}
void pf()
{
    int i,j;
    printf("-----------------------\n");
    for(i=1; i<=m; i++) {
        for(j=1; j<=n; j++){
            printf("%5.1f ",a[i][j]);
        }
        printf("\n");
    }
}
void solve()
{
    int i,j,k;
    for(i=1; i<=m; i++){
        if(cmp(a[i][i],0)==0){
            for(j=i+1; j<=m; j++){
                if(cmp(a[j][i],0)==1)
                    break;
            }
            for(k=1; k<=n; k++)
                swap(a[i][k],a[j][k]);
        }
        for(j=n; j>=i; j--){//这里一定要倒着减,因为是减到i之后的,前面的是不能减掉的.
            for(k=1; k<=m; k++) {
                if(k!=i){
                    a[k][j]-=(a[k][i]/a[i][i]*a[i][j]);//懂了!//精华啊,下次没看懂时就写出来,不要干想.
                }
            }
        }
    }
    for(i=1; i<=m; i++)
    {
         for(j=n;j>=i;j--) {
                a[i][j]/=a[i][i];//让最后一列的元素单位化
           }
    }
}
int main()
{
    int i,j;
    scanf("%d%d",&m,&n);
    for(i=1; i<=m; i++)
    {
        for(j=1; j<=n; j++)
        {
            scanf("%lf",&a[i][j]);
        }
    }
    solve();
    //pf();//可以自己自行选择是否打出来看看
}

这个精度就有要求了,尽量选择该列中较大的那个数,而且新增的判断0的那个还可以根据题目修改变为求矩阵的秩.好好想一想(写出来嘛)

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CLR(x) memset(x,0,sizeof(x))
#define ll long long int
#define db double
using namespace std;
const int maxn=205;
const ll inf=1e15+5;
const int INF = 1e8 + 5;
const int mod=1e9 + 7;
const db EPS=1e-2;
double a[205][205];
int vis[205];//记录全为0的那一行.
int m,n,cnt=0;
int cmp(db x, db y)
{
    db v;
    v=abs(x-y);
    if(v>=EPS)return 1;
    return 0;
}

void debug()
{
    printf("-----------------------\n");
    for(int i=1; i<=m; i++){
        for(int j=1; j<=n; j++){
            printf("%5.1f ",a[i][j]);
        }
        printf("\n");
    }
}

void solve()
{
    int sj,flag;
    db maxx;
    CLR(vis);
    for(int i=1; i<=m; i++){
        flag=0;
        maxx=-inf;
        for(int j=i; j<=m; j++){
            if(a[j][i]>maxx&&cmp(a[j][i],0)){
                sj=j;//用于交换的行数
                maxx=a[j][i];
                flag=1;
            }
        }
        if(!flag){
           vis[i]=1;//好好想想,用于判断(写出来就可以知道了).
            cnt++;//判断
            continue;
        }
        for(int k=1; k<=n; k++)
                swap(a[i][k],a[sj][k]);
        for(int j=n; j>=i; j--){//这里一定要倒着减,因为是减到i之后的,前面的是不能减掉的.
            if(vis[j])
                continue;//因为a[i]][i]是不能除的数.
            for(int k=1; k<=m; k++) {
                if(k!=i){
                    a[k][j]-=(a[k][i]/a[i][i]*a[i][j]);//懂了!//精华啊,下次没看懂时就写出来,不要干想.
                }
            }
        }
    }
    for(int i=1; i<=m; i++){
        if(!allzero[i]){
            for(int j=n;j>=0;j--){
                a[i][j]/=a[i][i];
            }
        }
    }
}
int main()
{
    int i,j;
    scanf("%d%d",&m,&n);
    for(i=1; i<=m; i++){
        for(j=1; j<=n; j++){
            scanf("%lf",&a[i][j]);
        }
    }
    solve();
    //debug();
    int p=m-cnt;
    if(p>=0)
        printf("%d\n",p);
    else
        printf("-1\n");
}

你可能感兴趣的:(高斯消元法(约当消元法))