高斯消元模板 要求输出解的情况(无穷解/无解)

1. 之前写的丑陋代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps=1e-7;
const int maxn=1000;
int n;//n个变量 n个方程
double A[maxn][maxn];
int Gauss() {//高斯消元 返回值 无解-- -1
//多解 -- 0 唯一解 -- 1(此时解保存在A[i][n+1]中)
int h,l,r;//h--行 l--列
for(h = 1,l = 1;h <= n && l <= n;++ h,++ l){//消系数矩阵(n*n)
r = h;
for(int i = h + 1;i <= n;++ i) if(fabs(A[i][l]) > fabs(A[r][l]) + eps) r=i;//找到当前列所有行中的最大值(做除法时减小误差)
if(r != h) for(int i = h;i <= n + 1;++ i) swap(A[r][i],A[h][i]);
if(fabs(A[h][l]) < eps) {--h;continue;}///当前列h行以下全为0(包括h行)
for(int i = h + 1;i <= n;++ i){
if(fabs(A[i][l]) < eps) continue;
for(int j = n + 1;j >= l;-- j) A[i][j]-=A[i][l]/A[h][l]*A[h][j];//加减消元
}
}
for(int i = h;i <= n;++ i) if(A[i][l] > eps) return -1;//系数均为0但结果不为0 无解
if(h <= n) return 0;//消元后所得方程不足n个(否则h为n+1) 有多解
for(int i = n; i ;-- i){//有唯一解 此时为严格的上三角矩阵 代入消元
for(int j = i + 1;j <= n + 1;++ j)
A[i][n+1]-=A[i][j]*A[j][n+1];
A[i][n+1]/=A[i][i];
}
return 1;
}
int main() {
scanf("%d",&n);
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= n + 1;++ j)
scanf("%lf",&A[i][j]);
int ans = Gauss();
if(ans<=0) printf("%d",ans);
else
for(int i = 1;i <= n;++i){
printf("x%d=", i);
if (fabs(A[i][n+1]) < eps) puts("0");
else printf("%.2f\n", A[i][n+1]);
}
return 0;
}

2. 改进后(更短更好理解)还是很丑陋???

/*
高斯约当消元法
把矩阵直接消成对角矩阵
与普通的高斯消元(消成阶梯矩阵再回代)相比计算量略大
但因为省略回代过程 代码更好写
*/
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=110;
int n,ans;
const double eps=1e-8;//控制精度
typedef double Matrix[maxn][maxn];//把二维数组重定义为矩阵
Matrix A;
int Guess(Matrix A,int n){
//传入增广矩阵和n的值 这里默认有n个未知数 n个方程 增广矩阵下标从1开始 有n行 n+1列
//若方程数有m个(m>=n) 可传入m 在此模板基础上微调
//返回值:-1--无实数解 0--有无穷多解 1--有唯一实数解 此时矩阵已被消成对角型
int r; bool flag = false;//flag 判无穷解
for(int i = 1; i <= n;++ i) {//i为枚举的行 也可以理解成当前要消第几个未知数
r = i;
for(int j = i + 1;j <= n;++ j) if(fabs(A[j][i]) > fabs(A[r][i])) r=j;//取包含该未知数的方程里系数绝对值最大的那个方程进行消元 可提高精度
if(fabs(A[r][i]) < eps) {//若最大系数绝对值为0 则包含该未知数的方程系数全是0
//此时说明【可能】有无穷解 之后有可能会出现无解的情况 所以只能先标记再处理 而不能直接返回无穷解
//若题目不要求输出具体是无穷解还是无解 可以直接return
flag = true; continue;}//放弃这一行 处理下一行(下一个未知数
if(r != i) swap(A[i],A[r]);//若系数绝对值最大的不是这一行 就交换这两行(swap直接交换两行的指针 不用for循环再交换)
for(int k = 1;k <= n;++ k) if(k != i)//与除了第i行以外其他行进行消元 直接消成对角型
for(int j = n + 1;j >= 1;-- j)//逆序枚举列 可以避免用中间变量(double)记录需要乘的倍数造成的精度误差
A[k][j] -= A[k][i] / A[i][i] * A[i][j];
}
//以下为判断解的情况 若题目中明确方程一定有解 或者 不要求输出具体是无解还是无穷解 可省略下面几行
//需要先判断是否无解再判断是否为无穷解
for(int i = 1,j;i <= n;++ i){//枚举每一行
for(j = 0;!A[i][j] && j <= n;++ j);//用指针j指向第一个这一行第一个不为零的数
if(j == n + 1 && A[i][j]) return -1;//若指向第n+1列说明系数全为零但结果不为零 方程无解
}
if(flag) return 0;//无穷解
return 1;//唯一解
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= n + 1;++ j)
scanf("%lf",&A[i][j]);
ans = Guess(A,n);
if(ans != 1) printf("%d",ans);
else
for (int i = 1; i <= n; ++i) {
printf("x%d=", i);
if (fabs(A[i][n+1]/A[i][i]) < eps) puts("0");//防止输出负零(double型)
else printf("%.2f\n", A[i][n+1]/A[i][i]);//已消成对角矩阵 第i+1列除以第i列就是答案
}
return 0;
}

洛谷P2455 [SDOI2006]线性方程组的更多相关文章

  1. 洛谷P2455 [SDOI2006]线性方程组(高斯消元)

    题目描述 已知n元线性一次方程组. 其中:n<=50, 系数是[b][color=red]整数<=100(有负数),bi的值都是整数且<300(有负数)(特别感谢U14968 mmq ...

  2. P2455 [SDOI2006]线性方程组(real gauss)

    P2455 [SDOI2006]线性方程组 (upd 2018.11.08: 这才是真正的高斯消元模板) 找到所消未知数(设为x)系数最大的式子,把它提上来 把这个式子的 x 系数约成1 把这个式子用 ...

  3. P2455 [SDOI2006]线性方程组

    P2455 [SDOI2006]线性方程组 真\(\cdot\)高斯消元模板题 由于各种hack数据被造出来~码量突增~,其实也就多了二三十行 将每行系数消到最多有一个非0数 特殊情况: 在过程同时 ...

  4. Luogu P2455 [SDOI2006]线性方程组 真•高斯消元板子

    果然如Miracle学长所说...调了一天...qwq..还是过不了线下的Hack upd after 40min:刚刚过了 就是多了一个判无解的操作... 当系数都为0,且常数项不为0时,即为无解. ...

  5. 【luogu P2455 [SDOI2006]线性方程组】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2455 无解:最后一列对应元素不为0,前面全是0. 无穷解:一行全是0. 嗯...在消元过程中不要直接拿矩阵元 ...

  6. C++ 洛谷 P2458 [SDOI2006]保安站岗 from_树形DP

    P2458 [SDOI2006]保安站岗 没学树形DP的,看一下. 题目大意:一棵树有N个节点,现在需要将所有节点都看守住,如果我们选择了节点i,那么节点i本身,节点i的父亲和儿子都会被看守住. 每个 ...

  7. 洛谷 P2458 [SDOI2006]保安站岗

    题目传送门 解题思路: 树形DP 可知一个点被控制有且仅有一下三种情况: 1.被父亲节点上的保安控制 2.被儿子节点上的保安控制 3.被当前节点上的保安控制 我们设dp[0/1/2][u]表示u节点所 ...

  8. [SDOI2006] 线性方程组

    洛谷 P2455 传送门 刚开始写了个消成上三角的,结果狂wa. 后来经过研究发现,消成上三角那种不能直接判断无解或无穷多解,需要其它的操作. 所以干脆学了个消成对角线的,写了一发A了. 其实两种消元 ...

  9. (伪)再扩展中国剩余定理(洛谷P4774 [NOI2018]屠龙勇士)(中国剩余定理,扩展欧几里德,multiset)

    前言 我们熟知的中国剩余定理,在使用条件上其实是很苛刻的,要求模线性方程组\(x\equiv c(\mod m)\)的模数两两互质. 于是就有了扩展中国剩余定理,其实现方法大概是通过扩展欧几里德把两个 ...

随机推荐

  1. Cesium 1.50重量级新功能测评

    概要 既Cesium 1.49中3dtile加载性能大幅提升以后,Cesium 1.50再次迎来几个重量级新功能: 1 地球裁切,这下相当于可以截取一部分地形影像数据,当作一个平面场景来用了! 2 射 ...

  2. NKOJ1469 通向自由的钥匙

    P1469通向自由的钥匙   时间限制 : 10000 MS   空间限制 : 65536 KB 问题描述 通向自由的钥匙被放n个房间里,这n个房间由n-1条走廊连接.但是每个房间里都有特别 的保护魔 ...

  3. Leetcode686.Repeated String Match重复叠加字符串匹配

    给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1. 举个例子,A = "abcd",B = " ...

  4. 阿里云MaxCompute 2019-7月刊

    您好,MaxCompute 2019.7月刊为您带来7月产品.技术最新动态,欢迎阅读. 导读 [发布]7月产品重要发布 [资讯]7月重要资讯 [文档]7月重要文档更新推荐 [干货]7月精选技术文章推荐 ...

  5. LUOGU P1081 开车旅行 (noip 2012)

    传送门 解题思路 这道题刚了一下午,主要就刚在set那里了.先写了一个暴力70分..之后优化预处理,看着大佬神犇们都用的什么双向链表之类的东西,本蒟蒻不会,又懒得手写平衡树,就拿了个set搞了搞,感觉 ...

  6. 解决pycharm新建工程项目都需要重新安装库问题

    在新建一个工程项目后,发现之前安装的库均不在了.想要使用的情况下还得重新安装.这样也太不智能了,一定会有解决的办法.查找相关文档后,发现在新建工程项目的时候需要进行选择是否使用以前的环境. 选择已存在 ...

  7. Python学习笔记(四)Python程序的控制结构

    在学习了 Python 的基本数据类型后,我们就要开始接触Python程序的控制结构,了解 Python 是如何使用控制结构来更改程序的执行顺序以满足多样的功能需求.如果有的小伙伴在之前学过C语言,j ...

  8. Python结合OpenCV学习资料

    1.sunny2038的专栏  http://blog.csdn.net/sunny2038 作者建立了一个学习系列.讲得非常具体,有非常多的主要的图像处理实例. 2. https://github. ...

  9. [Vue CLI 3] vue inspect 的源码设计实现

    首先,请记住: 它在新版本的脚手架项目里面非常重要 它有什么用呢? inspect internal webpack config 能快速地在控制台看到对应生成的 webpack 配置对象. 首先它是 ...

  10. 2018-3-4-dotnet-设计规范-·-结构体定义

    title author date CreateTime categories dotnet 设计规范 · 结构体定义 lindexi 2018-03-04 17:48:44 +0800 2018-2 ...