zoukankan      html  css  js  c++  java
  • POJ 2947 Widget Factory (高斯消元解同余方程组)

    题意:N种物品,M条记录,接写来M行,每行有K,str1,str2,表示第i个记录从星期str1到星期str2,做了K件物品,接下来的K个数为物品的编号。求做每个物品所需的时间,并且最后结果在3-9之间   很容易想到高斯消元。但是是带同余方程的高斯消元,开始建立关系的时候就要MOD 7   解此类方程式时最后求解的过程要用到扩展gcd的思想,举个例子,如果最后得到的矩阵为: 1  1   4 0  6   4 则6 * X2 % 7= 4 % 7  则相当于6 * X2 + 7 * Y = 4,利用扩展gcd则可求出X2为3,则第一个方程为 X1 * 1 % 7 + 1*3 % 7 = 4 % 7 则相当于 X1 + 7 * Y = 1  得到X1=1; 但其实这道题用扩展gcd真的大材小用了,因为模数是固定的而且很小就是7,所以直接枚举试就可以了~~  
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define MID(x,y) ((x+y)>>1)
    using namespace std;
    typedef long long LL;
    
    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;
    }
    const int MAX_EQU = 310;
    typedef struct  equation_set{
        int equ, var;               	//方程个数、变元个数,则增广矩阵有equ行、var+1列.
        int mat[MAX_EQU][MAX_EQU+1];  	//增广矩阵
        int x[MAX_EQU];            	 	//方程解向量
        bool free_x[MAX_EQU];       	//判断是否是不确定变元
    
        void init(int in_equ, int in_var);
        void debug();
        int gauss();
    }EQU;
    void equation_set::init(int in_equ, int in_var){
        equ = in_equ;
        var = in_var;
    
        memset(mat, 0, sizeof(mat));
        memset(x, 0, sizeof(x));
        memset(free_x, 1, sizeof(free_x));
    }
    void equation_set::debug(){
        for (int i = 0; i < equ; i ++){
            for (int j = 0; j < var; j ++)
                cout << mat[i][j] << " ";
            cout << mat[i][var] << endl;
        }
    }
    int equation_set::gauss(){
        int row = 0, col = 0;
        int max_row;
        while (row < equ && col < var){
            max_row = row;
            for (int i = row + 1; i < equ; i ++)
                if (abs(mat[i][col]) > abs(mat[max_row][col]))
                    max_row = i;
            if (max_row != row){
                for (int j = 0; j <= var; j ++){
                    int tmp = mat[row][j];
                    mat[row][j] = mat[max_row][j];
                    mat[max_row][j] = tmp;
                }
            }
            if (mat[row][col] == 0){
                col ++;
                continue;
            }
    		//普通方程组行阶梯化:
            for (int i = row + 1; i < equ; i ++){
                if (mat[i][col] != 0){
                    int LCM = lcm(abs(mat[i][col]), abs(mat[row][col]));
                    int ta = LCM  / abs(mat[i][col]), tb = LCM / abs(mat[row][col]);
                    if (mat[i][col] * mat[row][col] < 0)    tb = -tb;
                    for (int j = 0; j <= var; j ++)
                        mat[i][j] = ((mat[i][j] * ta - mat[row][j] * tb) % 7 + 7) % 7;
                }
            }
    
            row++, col++;
        }
        //debug();
    
        //1. 无解
        for (int i = row; i < equ; i++){
            if (mat[i][col] != 0) return -1;
        }
        //2.无穷解(这里只是计算出了确定变元,对于多解的计算,需要枚举自由变元的状态或者其他方法求解.)
        if (row < var){
            return 1;
        }
        //3.唯一解
        for (int i = row - 1; i >= 0; i --){
            int tmp = (mat[i][var] % 7 + 7) % 7;
            for (int j = var - 1; j > i; j --)
                tmp = ((tmp - x[j] * mat[i][j]) % 7 + 7) % 7;
            while(tmp % mat[i][i] != 0)
                tmp += 7;
            x[i] = (tmp / mat[i][i] % 7 + 7) % 7;
        }
        return 0;
    }
    int week(char s[]){
        if (strcmp(s, "MON") == 0)
            return 1;
        else if (strcmp(s, "TUE") == 0)
            return 2;
        else if (strcmp(s, "WED") == 0)
            return 3;
        else if (strcmp(s, "THU") == 0)
            return 4;
        else if (strcmp(s, "FRI") == 0)
            return 5;
        else if (strcmp(s, "SAT") == 0)
            return 6;
        else if (strcmp(s, "SUN") == 0)
            return 7;
    }
    int main(){
        int n,m;
        while(scanf("%d%d", &n, &m) == 2){
            if (n + m == 0)
                break;
            EQU E;
            E.init(m, n);
            for (int i = 0; i < m; i ++){
                int k;
                char s1[10], s2[10];
                scanf("%d", &k);
                scanf("%s%s", s1, s2);
                E.mat[i][n] = (week(s2) - week(s1) + 1) % 7;
                for (int j = 0; j < k; j ++){
                    int tmp;
                    scanf("%d", &tmp);
                    E.mat[i][tmp-1] ++;
                }
                for (int j = 0; j < n; j ++)
                    E.mat[i][j] %= 7;
            }
            //E.debug();
            int p = E.gauss();
            if (p == -1){
                printf("Inconsistent data.\n");
            }
            else if (p == 1){
                printf("Multiple solutions.\n");
            }
            else{
                for (int i = 0; i < n; i ++)
                    if(E.x[i] < 3)
                        E.x[i] += 7;
                for (int i = 0; i < n - 1; i ++)
                    printf("%d ", E.x[i]);
                printf("%d\n", E.x[n-1]);
            }
        }
    	return 0;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    JUnit测试框架的简单使用
    [转载文章] 单元测试与单元测试框架
    [转载文章]单元测试基本准则
    [转载文章]Google的Java编程风格指南(Java编码规范)
    设计模式实战——开发中经常涉及到的建造者模式
    痞子衡嵌入式:ARM Cortex-M文件那些事(7)- 反汇编文件(.s/.lst/.dump)
    痞子衡嵌入式:ARM Cortex-M文件那些事(6)- 可执行文件(.out/.elf)
    痞子衡嵌入式:ARM Cortex-M文件那些事(5)- 映射文件(.map)
    痞子衡嵌入式:ARM Cortex-M文件那些事(4)- 可重定向文件(.o/.a)
    痞子衡嵌入式:ARM Cortex-M文件那些事(3)- 工程文件(.ewp)
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114216.html
Copyright © 2011-2022 走看看