是这题卡精度还是我的思路有问题?

P2455 [SDOI2006] 线性方程组

George_Plover @ 2018-04-02 17:39:25

写这道题的时候,一直过不了,卡在判断0和-1上面。 我的思路:在最后消元求解的时候,把每一行的非主元移项成 ax=b的形式 a=0&&b=0 时,为无穷解 a=0&&b!=0时为无解

结果判断下来该输出0的时候输出了-1

然后突发奇想,想着会不会是被数据针对了,于是把数据反着输入,改变了消元的顺序,结果AC了

但是莫名其妙。。。 希望有大佬能帮忙看看,谢谢!

AC码(相较于WA,只改变了输入输出): ~

include <cmath>

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=201;
int n;
double a[MAXN][MAXN],b[MAXN],X[MAXN];
void guass(int x)
{
    double maxx=0.000000;
    int k=x;
    for(int i=x;i<=n;i++)
    {
        if(abs(a[i][x])>maxx)
        {
            maxx=abs(a[i][x]);k=i;
        }
    }
    for(int i=1;i<=n;i++)
        swap(a[x][i],a[k[i]);
    swap(b[x],b[k]);    
    for(int i=x+1;i<=n;i++)
    {
        double p=a[i][x]/a[x][x];
        b[i]-=b[x]*p;
        for(int j=x;j<=n;j++)
        {
            a[i][j]-=p*a[x][j];
        }
    }
}
int getans()
{
    for(int i=n;i>0;i--)
    {
        X[i]=b[i];
        for(int j=n;j>i;j--)X[i]-=X[j]*a[i][j];
        if(abs(a[i][i])<0.00001)
        {
            if(abs(b[i])<0.00001)return 0;
            return -1;
        }
        X[i]/=a[i][i];
    }
    return 1;
}
int main()
{

    scanf("%d",&n);

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        scanf("%lf",&a[i][n-j+1]);
     scanf("%lf",&b[i]);
    }   
    for(int i=1;i<=n;i++)guass(i);
    int Pan=getans();
    if(Pan!=1)
    {
        printf("%d\n",Pan);
        return 0;
    }       
    for(int i=n;i>0;i--)
    {
        if(abs(X[i])<0.0005)
        {
            printf("x%d=%d\n",i,0);
        }
        else printf("x%d=%.2f\n",n-i+1,X[i]);
    }
    return 0;
}

by wcwac @ 2018-04-02 21:57:45

你粘代码时掉字了 编译不了

你可以试试这个数据

6
1 2 3 4 5 6 10
0 0 1 2 3 4 15
0 0 0 2 6 7 30
0 0 0 0 6 8 10
0 0 0 0 0 1 30
0 0 0 0 0 0 0

@nieshaoheng


by George_Plover @ 2018-04-03 07:53:53

@wcac 谢谢(粘掉了cmath)


by George_Plover @ 2018-04-03 07:58:08

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=201;
int n;
double a[MAXN][MAXN],b[MAXN],X[MAXN];
void guass(int x)
{
    double maxx=0.000000;
    int k=x;
    for(int i=x;i<=n;i++)
    {
        if(abs(a[i][x])>maxx)
        {
            maxx=abs(a[i][x]);k=i;
        }
    }
    for(int i=1;i<=n;i++)
        swap(a[x][i],a[k][i]);
    swap(b[x],b[k]);    
    for(int i=x+1;i<=n;i++)
    {
        double p=a[i][x]/a[x][x];
        b[i]-=b[x]*p;
        for(int j=x;j<=n;j++)
        {
            a[i][j]-=p*a[x][j];
        }
    }
}
int getans()
{
    for(int i=n;i>0;i--)
    {
        X[i]=b[i];
        for(int j=n;j>i;j--)X[i]-=X[j]*a[i][j];
        if(abs(a[i][i])<0.00001)
        {
            if(abs(b[i])<0.00001)return 0;
            return -1;
        }
        X[i]/=a[i][i];
    }
    return 1;
}
int main()
{

    scanf("%d",&n);

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        scanf("%lf",&a[i][n-j+1]);
     scanf("%lf",&b[i]);
    }   
    for(int i=1;i<=n;i++)guass(i);
    int Pan=getans();
    if(Pan!=1)
    {
        printf("%d\n",Pan);
        return 0;
    }       
    for(int i=n;i>0;i--)
    {
        if(abs(X[i])<0.0005)
        {
            printf("x%d=%d\n",i,0);
        }
        else printf("x%d=%.2f\n",n-i+1,X[i]);
    }
    return 0;
}

重新粘了一份


by Starrydream @ 2018-10-24 07:39:23

@wcac 这种数据需要特判吗?毕竟高斯消元会判断无穷多解


|