zoukankan      html  css  js  c++  java
  • Gambler Bo (高斯消元求特解)

    对于图中的每一个点假设点击Xi * m + j 然后每个点都有那么对于每一个点可以列举出一个方程式,n*m个点解n*m个未知数。利用高斯消元就可以解决。

    问题就在这个题目可能不止有一个特,所以我们需要求解的时特解。然后那一个求解的我看不懂。

    #include <bits/stdc++.h>
    using namespace std ;
    
    const int maxn = 35 * 35;
    int n, m, cnt;
    int id[35][35], data[35][35], a[maxn][maxn], x[maxn];
    
    int gcd(int a, int b){
        return b?gcd(b, a%b) : a;
    }
    
    int lcm(int a, int b){
        return a / gcd(a, b) * b;
    }
    
    void init(){
        memset(x, 0, sizeof(x));
        memset(a, 0, sizeof(a));
        for(int i = 1; i <= n; i ++){
            for(int j = 1; j <= m; j ++){
                a[id[i][j]][cnt] = (3 - data[i][j])%3;
                a[id[i][j]][id[i][j]] = 2;
                if( i > 1) a[id[i][j]][id[i - 1][j]] = 1;
                if( j > 1) a[id[i][j]][id[i][j - 1]] = 1;
                if( i < n) a[id[i][j]][id[i + 1][j]] = 1;
                if( j < m) a[id[i][j]][id[i][j + 1]] = 1;
            }
        }
    }
    
    void gaussi(){
        for(int i = 1; i < cnt; i ++){
            int top = i;
            for(int j = i + 1; j < cnt; j ++)
                top = abs(a[j][i]) > abs(a[top][i]) ? j : top;
            if(a[top][i]){
                for(int j = i; j <= cnt; j ++)
                    swap(a[top][j], a[i][j]);
                for(int j = i + 1; j < cnt; j ++)
                if(a[j][i]){
                    int d = lcm(a[j][i], a[i][i]);
                    int x1 = d/a[j][i], x2 = d/a[i][i];
                    for(int k = i; k <= cnt; k ++)
                        a[j][k] = ((a[j][k] * x1 - a[i][k] * x2)%3 + 3) % 3;
                }
            }
        }
        int ans = 0;
        for(int i = cnt - 1; i > 0; i --){
            x[i] = a[i][cnt];
            for(int j = i + 1; j < cnt; j ++)
                x[i] = ((x[i] - a[i][j] * x[j])%3 + 3)%3;
            x[i] = a[i][i] * x[i] % 3;
            ans += x[i];
        }
        printf("%d
    ", ans);
        for(int i = 1; i < cnt; i ++){
            while(x[i]){
                printf("%d %d
    ", (i - 1)/m + 1, (i - 1)%m + 1);
                x[i] --;
            }
        }
    
    }
    
    int main () {
        int T ;scanf("%d",&T);
        while(T -- ){
            cnt = 1;
            scanf("%d%d",&n,&m);
            for(int i = 1; i <= n; i ++)
                for(int j = 1; j <= m; j ++)
                    scanf("%d",&data[i][j]), id[i][j] = cnt++;
            init();
            gaussi();
        }
        return 0 ;
    }
    more crazy more get!
  • 相关阅读:
    Android 项目结构图
    MySQL的简单使用
    MySql简易配置
    SQL Server 2008 R2 错误代码:233
    C#设置输入框只输入数字
    【学习笔记】JAva编程思想之多态
    【Java之对象清理】finalize()的用途
    【错误总结】java.lang.NoClassDefFoundError: org/objectweb/asm/ClassVisitor
    【学习笔记】Struts2之配置处理结果
    【学习笔记】Struts2之一个Action包含多个控制处理逻辑
  • 原文地址:https://www.cnblogs.com/wethura/p/9795752.html
Copyright © 2011-2022 走看看