当前位置: 首页 > news >正文

高斯消元——解线性方程组+球形空间产生器+开关问题

传送门:https://www.acwing.com/activity/content/11/

思路:

把原矩阵变成阶梯型矩阵解题步骤:

1.找到绝对值最大的一行。

2.将该行和最上面未处理好的一行交换位置

3.将该行第一个数变成1

4.将1这一列下面的所有数变成0;
代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=110,M=5e4+10;
const double eps=1e-6;
int n;
double a[N][N];
int gauss()
{
    int c,r;
    for(c=0,r=0;c<n;c++)
    {
        int t=r;
        for(int i=r;i<n;i++)
            if(fabs(a[i][c])>fabs(a[t][c]))  ///找到绝对值最大的一行
            t=i;

        if(fabs(a[t][c])<eps) continue;  ///假如该列所有数都是0了就跳过这一列,从当前行的下一列开始处理

        for(int i=c;i<=n;i++) swap(a[t][i],a[r][i]); ///和现在的第一行交换位置
        for(int i=n;i>=c;i--) a[r][i]/=a[r][c];  ///从后往前处理让该行第一个数变成1
        for(int i=r+1;i<n;i++)
            if(fabs(a[i][c])>eps)   ///只要1下面的数不是0,就把该列下面的每一个数都变成0
            for(int j=n;j>=c;j--)
            a[i][j]-=a[r][j]*a[i][c];  ///上面有个1,所以0右边的数只要减去的最左边的数乘上对应列数的数即可
        r++;
    }
    if(r<n)  ///如果最后方程的数量不等于n,要么无解,要么无穷解
    {
        for(int i=r+1;i<n;i++)
            if(fabs(a[i][n])>eps) ///出现0!=0的情况就无解
            return 2;
        return 1;
    }
    for(int i=n-1;i>=0;i--)  ///这里一步是将阶梯型矩阵的最后一位变成约化阶梯型矩阵下的结果。
        for(int j=i+1;j<n;j++)
        a[i][n]-=a[i][j]*a[j][n];
    return 0;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<=n;j++)
        cin>>a[i][j];
    int t=gauss();
    if(t==0)
    {
        for(int i=0;i<n;i++) printf("%.2lf\n",a[i][n]);
    }else if(t==1) puts("Infinite group solutions");
    else puts("No solution");
    return 0;
}

传送门:207. 球形空间产生器 - AcWing题库

思路:在一个普通的二维平面上的球的坐标是(x,y),可以用三个点来确定,公式就是

(a1-x)^2+(b1-y1)^2=R^2    (a2-x)^2+(b2-y1)^2=R^2  (a3-x)^2+(b3-y1)^2=R^2

扩展到n维的时候就需要用一个n元组来表示圆心[x1,x2,x3...,xn],用n+1个点的坐标确定一个圆:有如下

(a01-x1)^2+(a02-x2)^2+(a03-x3)^2+...+(a0n-xn)^2=R^2   第0条

(a11-x1)^2+(a12-x2)^2+(a13-x3)^2+...+(a1n-xn)^2=R^2   第1条

(a21-x1)^2+(a22-x2)^2+(a23-x3)^2+...+(a2n-xn)^2=R^2  第2条

.

(an1-x1)^2+(an2-x2)^2+(an3-x3)^2+...+(ann-xn)^2=R^2  第n条

高斯消元所用的是线性方程组,这里要用n条方程都减去第0条得到n条线性方程。

以第一条减去第二条为例,相减并移项后有如下

2(a11-a01)x1+2(a12-a02)x2+...+2(a1n-a0n)xn==a11^2+a12^2+...a1n^2-a01^2+a02^2-...a0n^2

此时x1到xn这n个数以外都是常数。

代码:

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=15;
const double eps=1e-6;
int n;
double a[N][N];
double b[N][N];
void gauss()
{
  for(int c=1,r=1;c<=n;r++,c++)
    {
        int t=r;
        for(int i=r+1;i<=n;i++)
            if(fabs(b[i][c])>fabs(b[t][c])) t=i;

        for(int i=c;i<=n+1;i++) swap(b[t][i],b[r][i]);

        for(int i=n+1;i>=c;i--) b[r][i]/=b[r][c];

        for(int i=r+1;i<=n;i++)
            for(int j=n+1;j>=c;j--)
            b[i][j]-=b[i][c]*b[r][j];
    }
    //转化为约化阶梯型矩阵
    for(int i=n;i>1;i--)
    for(int j=i-1;j;j--)
    {
        b[j][n+1]-=b[i][n+1]*b[j][i];
        b[j][i]=0;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
        for(int j=1;j<=n;j++)
        scanf("%lf",&a[i][j]);

    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
    {
        b[i][j]+=2*(a[i][j]-a[0][j]);
        b[i][n+1]+=a[i][j]*a[i][j]-a[0][j]*a[0][j];
    }
    gauss();
    for(int i=1;i<=n;i++)
        printf("%.3lf ",b[i][n+1]);
    return 0;
}

传送门:208. 开关问题 - AcWing题库

思路:将原问题转化成一个解异或线性方程组的问题;

用一个异或线性方程表示一个灯的状态的改变,每个开关怎么按可以使这条式子的对应开关产生怎么的变化就是一个异或的关系。

先从简单的样例入手,现在设一个三元组[x1,x2,x3]分别表示三个开始有没有产生按。

现在有1可以影响2,  2 可以影响1,2,3 ,3可以影响3 ,初始态为0,0,0,结果态为1,1,1,可以列出以下的三个方程

x1^x2  =x1(使得x1如何变化)           ==> 1    1    0          1

x1^x2  =x2(使得x2如何变化)           ==> 1    1    0          1

x2^x3  =x3(使得x3如何变化)           ==> 0    1    1          1

只要上面的异或线性方程组有解,那么原问题就一定有解,如果有自由变量的话,因为么一个灯的状态只有两个,故有k个自由变量就有2^k个解决方案。

代码:

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=36;
const double eps=1e-6;
int n;
int a[N][N];
int gauss()
{
    int r,c;
    for(r=1,c=1;c<=n;c++)
    {
        int t=r;
        for(int i=r+1;i<=n;i++)
            if(a[i][c])
            t=i;

        if(!a[t][c])continue;
        for(int i=c;i<=n+1;i++) swap(a[t][i],a[r][i]);

        for(int i=r+1;i<=n;i++)
            for(int j=n+1;j>=c;j--)
            a[i][j]^=a[i][c]&a[r][j];
        r++;
    }
    int res=1;
    if(r<n+1)
    {
        for(int i=r;i<=n;i++)
        {
            if(a[i][n+1]) return -1;
            res*=2;
        }
    }
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(a,0,sizeof a);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i][n+1]);

        for(int i=1;i<=n;i++)
        {
            int m;
            scanf("%d",&m);
            a[i][n+1]^=m;
            a[i][i]=1;
        }

        int x,y;
        while(scanf("%d%d",&x,&y),x||y)
        {
            a[y][x]=1;
        }
        int t=gauss();
        if(t==-1) puts("Oh,it's impossible~!!");
            else
            printf("%d\n",t);
    }
    return 0;
}

相关文章:

  • 龙采哈尔滨建站公司/注册网站平台
  • ppp模式在网站建设的/北京百度seo点击器
  • 婚纱网站模板/最好的bt磁力搜索引擎
  • 湖北工程建设招投标中心网站/西安百度快速排名提升
  • wordpress网站登录/查指数
  • php学院网站源码/世界500强企业
  • Node.js查询MySQL并返回结果集给客户端
  • 《设计模式》适配器模式
  • python编程 input输入函数
  • <算法入门>_基础入门篇一
  • 答应我从这篇文章开始你的C语言之旅吧
  • VC对11类NFT初创企业的看法与建议
  • Spring5中类型转换器
  • 设计模式之桥接模式
  • SCI论文修稿时间延长信的申请格式-论文投稿经验总结-第4期
  • 【牛客网】数组中值出现了一次的数字
  • 【算法】【排序模块】冒泡排序和希尔排序
  • 安卓通过USB控制Arduino