高斯消元法

顾名思义就是我们初中所知的消元方程,用来解方程的,但是如果自己手动去实现的话,还是有一部分难度的,因此我们也会用到线代这门科目,因为这是实现计算自动化的关键步骤

现在这里放上高斯消元的板子(可以用于区分有解,有无数组解和无解的情况)

void Gauss() //高斯消元
{
    for(int i=1;i<=n;i++)
    {
        int maxn=i;
        for(int j=1;j<=n;j++) 
        {
            if(fabs(a[j][j])>eps&&j<i) 
			{
				continue;//若在i前,且的确已对应一项系数,不可用
			}
            if(fabs(a[j][i])>fabs(a[maxn][i]))
            {
                maxn=j;
            }
        }
        if(maxn!=i)
        swap(a[maxn],a[i]);
        if(fabs(a[i][i])<=eps) 
		{
			continue;
		}
		
		double div=a[i][i];
		for(int j=i;j<=n+1;j++)
		{
			a[i][j]/=div;
		}
        for(int j=1;j<=n;j++)
        {
            if(i==j) 
			continue;
            div=a[j][i];
            for(int k=i;k<=n+1;k++)
            {
                a[j][k]-=div*a[i][k];
            }
        }
    }
}

 例题

P3389 【模板】高斯消元法

 

纯板子题甚至不需要区分有无数组解和无解的情况,在上面板子优化代码即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
double a[105][105];
double ans[105];//统计每个数的结果
double flag=1e-7;//用来判断是否会小于0 
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n+1;j++)
		{
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		int r=i;//用来找到最大行
		for(int j=i+1;j<=n;j++)
		{
			if(fabs(a[r][i])<fabs(a[j][i]))
			{
				r=j;
			}
		} 
		if(fabs(a[r][i])<flag)
		{
			cout<<"No Solution\n";
			return 0;
		}
		if(i!=r)
		{
			swap(a[i],a[r]);
		}
		double div=a[i][i];
		for(int j=i;j<=n+1;j++)
		{
			a[i][j]/=div;
		}
		for(int j=i+1;j<=n;j++)
		{
			div=a[j][i];
			for(int k=i;k<=n+1;k++)
			{
				a[j][k]-=div*a[i][k];
			}
		}
	 } 
	 
	ans[n]=a[n][n+1];
	for(int i=n-1;i>=1;i--)
	{
		ans[i]=a[i][n+1];
		for(int j=i+1;j<=n;j++)
		{
			ans[i]-=(a[i][j]*ans[j]);
		}
	}
	for(int i=1;i<=n;i++)
	{
		printf("%.2lf\n",ans[i]);
	}
	return 0;
} 

P2455 [SDOI2006] 线性方程组

就是加了一个需要区分无数组解和无解的情况,这个直接用上面的板子即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
double a[55][55];
double eps=1e-7;
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n+1;j++)
		{
			cin>>a[i][j];
		}
	}
	
	//高斯消元法 
	for(int i=1;i<=n;i++)
	{
		int r=i;
		for(int j=1;j<=n;j++)
		{
			if(fabs(a[j][j])>eps&&j<i)
			{
				continue;
			}
			if(fabs(a[j][i])>fabs(a[r][i]))
			{
				r=j;
			}
			if(r!=i)
			{
				swap(a[i],a[r]);
			}
			if(fabs(a[i][i])<=eps) 
		    {
		    	continue;
	    	}
			double div=a[i][i];
			for(int j=i;j<=n+1;j++)
			{
				a[i][j]/=div;
			}
			for(int j=1;j<=n;j++)
			{
				if(i==j)//防止自己行-自己行 
				continue;
				div=a[j][i];
				for(int k=i;k<=n+1;k++)
				{
					a[j][k]-=div*a[i][k];
				}
			}
		}
	}
	
	//特判情况
	int flag=1;
	for(int i=1;i<=n;i++)
	{
		if(fabs(a[i][i])<=eps)
		{
			if(fabs(a[i][n+1])>eps)
			{
				flag=-1;
			}
			else if(flag!=-1)
			{
				flag=0;
			}
		}
	} 
	
	if(flag!=1)
	{
		cout<<flag<<"\n";
	}
	else
	{
		for(int i=1;i<=n;i++)
		{
			cout<<"x"<<i<<"=";
			printf("%.2lf\n",fabs(a[i][n+1])<eps?0:a[i][n+1]);
		}
	}
	return 0;
}

 P4035 [JSOI2008] 球形空间产生器

高斯消元的变式,推一下就出公式了,很简单,明天讲解为什么

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
double a[15][15];
double mp[15][15];
double eps=1e-7;

void Gauss() //高斯消元
{
    for(int i=1;i<=n;i++)
    {
        int maxn=i;
        for(int j=1;j<=n;j++) 
        {
            if(fabs(a[j][j])>eps&&j<i) 
			{
				continue;//若在i前,且的确已对应一项系数,不可用
			}
            if(fabs(a[j][i])>fabs(a[maxn][i]))
            {
                maxn=j;
            }
        }
        if(maxn!=i)
        swap(a[maxn],a[i]);
        if(fabs(a[i][i])<=eps) 
		{
			continue;
		}
		
		double div=a[i][i];
		for(int j=i;j<=n+1;j++)
		{
			a[i][j]/=div;
		}
        for(int j=1;j<=n;j++)
        {
            if(i==j) 
			continue;
            div=a[j][i];
            for(int k=i;k<=n+1;k++)
            {
                a[j][k]-=div*a[i][k];
            }
        }
    }
}

signed main()
{
	cin>>n;
	for(int i=1;i<=n+1;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>mp[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int k=1;k<=n;k++)
		{
			a[i][k]=mp[i+1][k]-mp[i][k];
			a[i][n+1]+=(mp[i+1][k]*mp[i+1][k]-mp[i][k]*mp[i][k])/2;
		}
	}
	Gauss();
	for(int i=1;i<=n;i++)
	{
		printf("%.3lf ",fabs(a[i][n+1])<=eps?0:a[i][n+1]);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值