高斯消元 zoj 3645 poj 1222/XOR消元

来源:互联网 发布:宋朝生活知乎 编辑:程序博客网 时间:2024/06/07 23:12
double  a[maxn][maxn] , x[maxn] ;  //a[i][j] 系数矩阵 , a[i][n+1]  = y[i] , x解int     n ;   //n个方程void    guass(){        int i , j , k ;        double  sum , rate ;        for(k = 1 ; k < n ;  k++){             for(i = j = k ; i <= n ; i++) j = fabs(a[i][k]) > fabs(a[j][k]) ? i : j ;             for(i = k ; i <= n+1 ; i++)  swap(a[j][i] , a[k][i]) ;             for(i = k+1 ; i <= n ; i++)                 for(rate = a[i][k]/a[k][k] , j = k ; j <= n+1 ; j++)                      a[i][j] -= a[k][j]*rate ;        }        for(i = n ; i >= 1 ; i--){            for(sum = 0 , j = i+1 ; j <= n ; sum += a[i][j]*x[j],j++) ;            x[i] = (a[i][n+1] - sum)/a[i][i] ;        }}double  Fix(double x){   // 将 -0.000 变成 0.00 ,结果输出Fix(x[])        if(fabs(x) < 1e-4) return 0 ;        return x ;}

 

 

另一个版本的高斯消元

double  a[Max_N][Max_N], x[Max_N],b[Max_N][Max_N]; // 系数矩阵,double型void guass(int n){    int i,j,k;// 这里 i表示行,j表示列,k表示某行的某列(确定一个元素)    for(i=0; i<n; i++)        for(j=0; j<n; j++)            b[i][j]=a[i][j];    for(i=0; i<n; i++)        b[i][n] = x[i];    for(j=0; j<n; j++){        for(k=i=j; i<n; i++) k = fabs(b[i][j]) > fabs(b[k][j]) ? i : k ;        for(i=0; i<=n; i++)  swap(b[j][i],b[k][i]);        //把正在处理的那一行的对角线上的系数变成1,同一行除b[j][j],该位置的系数不处理        for(i=j+1 ; i<=n; i++) b[j][i] /= b[j][j];        for(i=0; i<n; i++){            if(i != j)                for(k=j+1; k<=n; k++) b[i][k] -= b[i][j]*b[j][k]; // 做行变换,被消的同一列系数不处理        }    }}

 

 

zoj 3645 BiliBili

题目来源:   http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4835

 

题目意思很明显

给你一个方程组 让你求(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11)

但是方程组的形式是一个二次方程组

(ai1-x1)^2 + (ai2-x2)^2 +(ai3-x1)^2 + (ai4-x2)^2 +(ai5-x1)^2 + (ai6-x2)^2 +(ai7-x1)^2 + (ai8-x2)^2 + (ai9-x2)^2 +(ai10-x1)^2 + (ai11-x2)^2  = dis ^2

于是我们可以发现 用两个方程相减就可以得到一个一次方程组。 这样操作11次得到一个新的方程组,然后用高斯消元法求解即可。

代码如下:

 

using namespace std ;const double pi= acos(-1);#define arc(x) (x / 180 * pi)typedef long long LL ;const double EPS = 1e-8;const int Max_N = 15;double  a[Max_N][Max_N], d[Max_N],b[Max_N][Max_N]; // 系数矩阵,double型int n; // 方程的个数void guass(){    int i,j,k;    for(j=0; j<n; j++){        for(k=i=j; i<n; i++) k = fabs(b[i][j]) > fabs(b[k][j]) ? i : k ;        for(i=0; i<=n; i++)  swap(b[j][i],b[k][i]);        for(i=j+1 ; i<=n; i++) b[j][i] /= b[j][j];        for(i=0; i<n; i++){            if(i != j)                for(k=j+1; k<=n; k++) b[i][k] -= b[i][j]*b[j][k];        }    }}int main(){    int t;    scanf("%d",&t);    while(t--){        n=11;        for(int i=0; i<=n; i++){            for(int j=0; j<n; j++)                scanf("%lf",&a[i][j]);            scanf("%lf",&d[i]);        }        memset(b,0,sizeof(b));        for(int i=1; i<=n; i++){            for(int j=0; j<n; j++){                b[i-1][j] = 2*(a[i][j] - a[i-1][j] );                b[i-1][n] += a[i][j]*a[i][j] - a[i-1][j]*a[i-1][j];            }        }        for(int i=0; i<n; i++) b[i][n] += d[i]*d[i] - d[i+1]*d[i+1];        guass();        for(int i=0; i<n-1; i++)            printf("%.2lf ",b[i][n] + EPS);  // 输出时注意这里的判断, 处理-0.0000        printf("%.2lf\n",b[n-1][n] + EPS);    }    return 0;}

 

 poj 1222 EXTENDED LIGHTS OUT

题目来源:    http://poj.org/problem?id=1222

分析:转化为横坐标为灯(灯0,灯1,。。。,灯29)纵坐标为开关(开关0,开关1,。。。,开关29),记为矩阵A,矩阵A与灯的初始状态无关,A(i,j)=1表示开关j对灯i有影设矩阵X,X是30*1的矩阵,表示开关是否需要打开。X(i,0)=1表示开关i需要打开。矩阵X是待求的。设矩阵B 30*1,表示结果。B只与灯的初始状态有关,初始时灯i是开着的,则B(i,0)=1。解方程AX=B。

 

代码如下:

 

const int Max_N = 35;int a[Max_N][Max_N]; // 系数矩阵,double型,AX = Yint n; // 方程的个数 a[i][n]存储的是Y向量void guass(){    int i,j,k; // i表示行,j表示列    for(i=0; i<n; i++){        for(k=i; k<n; k++) //寻找不为零的 a[i][i],通过交换            if(a[k][i]) break;        for(j=0; j<=n; j++) swap(a[k][j], a[i][j]);        for(j=0; j<n; j++)            if(i != j && a[j][i]) // 如果a[j][i] == 0 ,则该行不需要变换                for(k=0; k<=n; k++)                    a[j][k] ^= a[i][k];    }}int main(){    int t,u=1;    scanf("%d",&t);    while(t--){        int i,j;        n=30;        memset(a,0,sizeof(a));        for(i=0; i<n; i++)            scanf("%d",&a[i][n]); // Y value        for(i=0; i<n; i++){            a[i][i]=1;            if(i>5) a[i][i-6] = 1 ;// up a[i][j] 表示第i个灯被第j个开关影响            if(i<24) a[i][i+6] =1 ; // down            if(i%6) a[i][i-1] = 1 ; // left            if(i%6 != 5) a[i][i+1] = 1 ; //right        }        guass();        printf("PUZZLE #%d\n",u++);        for(i=0; i<n; i++){            if(i%6 != 5)                printf("%d ",a[i][n]);            else                printf("%d\n",a[i][n]);        }    }    return 0;}

 

0 0
原创粉丝点击