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

    题目地址:POJ 2947

    题意:N种物品。M条记录,接写来M行,每行有K。Start,End,表述从星期Start到星期End,做了K件物品。接下来的K个数为物品的编号。

    此题注意最后结果要调整到3-9之间。

    思路:

    非常easy想到高斯消元。

    可是是带同余方程式的高斯消元,開始建立关系的时候就要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。

    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    #include <sstream>
    #include <algorithm>
    #include <set>
    #include <queue>
    #include <stack>
    #include <map>
    using namespace std;
    typedef long long LL;
    const int inf=0x3f3f3f3f;
    const double pi= acos(-1.0);
    const double esp=1e-6;
    const int MAXN=310;
    int aug[MAXN][MAXN];<span style="background-color: rgb(255, 255, 255);">//增广矩阵行数为m,分别为0到m-1,列数为n+1,分别为0到n.</span>
    int x[MAXN];//解集
    int free_num;
    int m,n;//m个方程。n个变元
    int gcd(int a,int b) {
        int r;
        while(b!=0) {
            r=b;
            b=a%b;
            a=r;
        }
        return a;
    }
    int lcm(int a,int b) {
        return a/gcd(a,b)*b;
    }
    /*void Debug(void)
    {
        puts("");
        int i,j;
        for(i=0;i<m;i++){
            for(j=0;j<n+1;j++){
                cout << matrix[i][j] << " ";
            }
            cout << endl;
        }
        cout << endl;
    }*/
    int trans(char *str) {
        if(strcmp(str,"MON")==0) return 1;
        else if(strcmp(str,"TUE")==0) return 2;
        else if(strcmp(str,"WED")==0) return 3;
        else if(strcmp(str,"THU")==0) return 4;
        else if(strcmp(str,"FRI")==0) return 5;
        else if(strcmp(str,"SAT")==0) return 6;
        else if(strcmp(str,"SUN")==0) return 7;
    }
    // 高斯消元法解方程组(Gauss-Jordan elimination).(-1表示无解。
    //0表示唯一解。大于0表示无穷解。并返回自由变元的个数)
    int Gauss() {
        int i,j;
        int row,col,max_r;// 当前这列绝对值最大的行;
        int LCM;
        int ta,tb;
        int tmp;
        for(row=0,col=0; row<m&&col<n; row++,col++) {
            // 枚举当前处理的行.
            // 找到该col列元素绝对值最大的那行与第row行交换.(为了在除法时减小误差)
            max_r=row;
            for(i=row+1; i<m; i++) {
                if(abs(aug[i][col])>abs(aug[max_r][col]))
                    max_r=i;
            }
            if(max_r!=row) {
                // 与第row行交换
                for(j=row; j<n+1; j++)
                    swap(aug[row][j],aug[max_r][j]);
            }
            if(aug[row][col]==0) {
                // 说明该col列第row行下面全是0了,则处理当前行的下一列.
                row--;
                continue;
            }
            for(i=row+1; i<m; i++) {
                // 枚举要删去的行.
                if(aug[i][col]!=0) {
                    LCM=lcm(abs(aug[i][col]),abs(aug[row][col]));
                    ta=LCM/abs(aug[i][col]);
                    tb=LCM/abs(aug[row][col]);
                    if(aug[i][col]*aug[row][col]<0) tb=-tb;//异号的情况是相加
                    for(j=col; j<n+1; j++) {
                        aug[i][j]=(((aug[i][j]*ta-aug[row][j]*tb)%7+7)%7);
                    }
                }
            }
        }
        //Debug();
        // 1. 无解的情况: 化简的增广阵中存在(0, 0, ..., a)这种行(a != 0).
        for(i=row; i<m; i++) {
            if(aug[i][col]!=0)  return -1;
        }
        // 2. 无穷解的情况: 在n * (n + 1)的增广阵中出现(0, 0, ..., 0)这种行,即说明没有形成严格的上三角阵.
        // 且出现的行数即为自由变元的个数.
        if(row<n){
            return n-row;
        }
         // 3. 唯一解的情况: 在n * (n + 1)的增广阵中形成严格的上三角阵.
        // 计算出Xn-1, Xn-2 ... X0.
        for(i=n-1; i>=0; i--) {
            tmp=aug[i][n];//等式右边的数
            for(j=i+1; j<n; j++) {
                if(aug[i][j]!=0) tmp-=aug[i][j]*x[j];//把已知的解带入。减去,仅仅剩下,一个未知的解
                tmp=(tmp%7+7)%7;
            }
            while(tmp%aug[i][i]!=0)//外层每次循环都是为了求 a[i][i],由于它是每一个方程中唯一一个未知的变量(求该方程时)
                tmp+=7;//由于天数不确定,而aug[i][i]必须得为整数才干够,周期为7
            x[i]=(tmp/aug[i][i])%7;
        }
        return 0;
    }
    int main(void) {
        int nn,mm,i,j,k;
        int num;
        char Start[5],End[5];
        while(~scanf("%d %d",&nn,&mm)) {
            if(nn==0&&mm==0) break;
            n=m=0;
            memset(aug,0,sizeof(aug));
            for(i=0; i<mm; i++) {
                scanf("%d",&k);
                scanf("%s %s",Start,End);
                aug[i][nn]=((trans(End)-trans(Start)+1)%7+7)%7;
                for(j=1; j<=k; j++) {
                    scanf("%d",&num);
                    num--;
                    aug[i][num]++;
                    aug[i][num]%=7;//有反复的
                }
            }
            m=mm;
            n=nn;
            free_num = Gauss();
            if(free_num==0) {
                for(i=0; i<n; i++)
                    if(x[i]<3)//依据题意,每一个零件的加工时间在3-9天.
                        x[i]+=7;
                for(i=0; i<n-1; i++)
                    printf("%d ",x[i]);
                printf("%d
    ",x[i]);
            } else if(free_num==-1)
                puts("Inconsistent data.");
            else
                puts("Multiple solutions.");
        }
        return 0;
    }
    



  • 相关阅读:
    warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    Windows10+CLion+OpenCV4.5.2开发环境搭建
    Android解决部分机型WebView播放视频全屏按钮灰色无法点击、点击全屏白屏无法播放等问题
    MediaCodec.configure Picture Width(1080) or Height(2163) invalid, should N*2
    tesseract
    Caer -- a friendly API wrapper for OpenCV
    Integrating OpenCV python tool into one SKlearn MNIST example for supporting prediction
    Integrating Hub with one sklearn mnist example
    What is WSGI (Web Server Gateway Interface)?
    Hub --- 机器学习燃料(数据)的仓库
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7105810.html
Copyright © 2011-2022 走看看