zoukankan      html  css  js  c++  java
  • HDU 5755 高斯消元

    http://acm.hdu.edu.cn/showproblem.php?pid=5755

    题意:一个N*M的棋盘,每个点是0,1,2中的一个,在取模3的含义下,翻转一个这个+2,周围的4个加1.。。。

    思路:感慨一下知识面太狭隘了。。学习了一下高斯消元,这个题目其实就是高斯消元的一个经典题目。。每个结点的翻转次数都是一个变量。。猛地一看时间复杂度是n^3m^3但是高斯消元里面变量前的系数如果是0就不进行迭代了。。这么一看原题列出的增广矩阵明显是一个稀疏矩阵,一行最多只有五个系数非零。。那么就非常愉快的。。差不多可以莽一下大概n^2m^2的复杂度就过去了~

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MOD = 3;
    const int MAXN = 1000;
    int a[MAXN][MAXN];//增广矩阵
    int x[MAXN];//最后得到的解集
    inline int gcd(int a,int b){
        while(b != 0){
            int t = b;
            b = a%b;
            a = t;
        }
        return a;
    }
    inline int lcm(int a,int b){
        return a/gcd(a,b)*b;
    }
    void zgcd(long long a,long long b,int &d,int &x,int &y){
    
        if(!b){d=a;x=1;y=0;}
    
        else{zgcd(b,a%b,d,y,x);y-=x*(a/b);}
    
    }
    
    long long mod_r(long long b,long long p){
        int x,y,d;
        zgcd(b,p,d,x,y);
        if(d!=1) return -1;
        return (x%p+p)%p;
    }
    int Gauss(int equ,int var){
        int max_r,col,k;
        for(k = 0, col = 0; k < equ && col < var; k++,col++){
            max_r = k;
            for(int i = k+1; i < equ; i++)    if(abs(a[i][col]) > abs(a[max_r][col]))     max_r = i;
            if(a[max_r][col] == 0){
                k--;
                continue;
            }
            if(max_r != k)    for(int j = col; j < var+1; j++)     swap(a[k][j],a[max_r][j]);
            for(int i = k+1; i < equ; i++){
                if(a[i][col] != 0){
                    int LCM = lcm(abs(a[i][col]),abs(a[k][col]));
                    int ta = LCM/abs(a[i][col]);
                    int tb = LCM/abs(a[k][col]);
                    if(a[i][col]*a[k][col] < 0)tb = -tb;
                    for(int j = col; j < var+1; j++)      a[i][j] = ((a[i][j]*ta - a[k][j]*tb)%MOD + MOD)%MOD;
                }
            }
        }
        for(int i = k; i < equ; i++)   if(a[i][col] != 0)    return -1; //无解
       // if(k < var) return var-k;//多解
        for(int i = var-1; i >= 0; i--){
            int temp = a[i][var];
            for(int j = i+1; j < var; j++){
                if(a[i][j] != 0){
                    temp -= a[i][j]*x[j];
                    temp = (temp%MOD + MOD)%MOD;
                }
            }
            x[i] = (temp*mod_r(a[i][i],3))%MOD;
        }
        return 0;
    }
    int p[MAXN][2];
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            int n,m;
            scanf("%d%d",&n,&m);
            memset(a,0,sizeof(a));
            memset(x,0,sizeof(x));
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    int num;
                    scanf("%d",&num);
                    int idx=i*m+j;
                    p[idx][0]=i;
                    p[idx][1]=j;
                    a[idx][n*m]=(3-num)%3;
                    a[idx][idx]=2;
                    if(i-1>=0)  a[(i-1)*m+j][idx]=1;
                    if(i+1<n)   a[(i+1)*m+j][idx]=1;
                    if(j-1>=0)  a[i*m+j-1][idx]=1;
                    if(j+1<m)   a[i*m+j+1][idx]=1;
                }
            }
            Gauss(n*m,n*m);
            int cnt=0;
            for(int i=0;i<n*m;i++){
                cnt+=x[i];
            }
            cout<<cnt<<endl;
            for(int i=0;i<n*m;i++){
                for(int j=0;j<x[i];j++)
                    cout<<p[i][0]+1<<" "<<p[i][1]+1<<endl;
            }
        }
    }



  • 相关阅读:
    ie 中window.open无法带referrer
    es6 学习7 Set 和 Map 数据结构
    ES6 学习6 数组的扩展
    ES6 学习3 函数
    ES6学习之环境配置
    理解闭包
    javascript中实现继承的几种方式
    js 原型和原型链
    Vue学习之v-if与v-show的区别
    unity图集切成多张图片的方法
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672549.html
Copyright © 2011-2022 走看看