poj 2947 Widget Factory (高斯消元,解模线性方程)

21 篇文章 0 订阅

链接:poj 2947

题意:生产一些零件,已知零件种数,记录条数

记录只记录了某次生产从周几开始,周几结束,以及生产了哪些产品。

每件商品生产所需天数为3-9天。

求每样产品需要多少天才能完成。

若无解输出Inconsistent data.

有无穷解输出Multiple solutions.

有唯一解,输出其解

分析:根据题目所给信息,可以列出同余方程组,再根据高斯消元求解,

但还得判断是无解,无穷解,还是唯一解

1.系数矩阵的秩若与增广矩阵的秩不相等,则无解,否则有解

2.若有解,若增广矩阵的秩小于未知数的个数,则有无穷解

3.若有解,增广矩阵的秩等于未知数的个数,则有唯一解

有唯一解时,需要用扩展欧几里得解模线性方程

注:求矩阵的秩,先将矩阵化为阶梯型,有多少个非0行或者非0列,

矩阵的秩就为多少.矩阵的行秩等于矩阵的列秩


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MOD 7
using namespace std;
int m,n,matrix[310][310],ans[310];
int get_id(char s[])
{
    char week[8][5]={"","MON","TUE","WED","THU","FRI","SAT","SUN"};
    int i;
    for(i=1;i<=7;i++)
        if(strcmp(s,week[i])==0)
            break;
    return i;
}
int ex_gcd(int a,int b,int &x,int &y)
{
    int t,d;
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    d=ex_gcd(b,a%b,x,y);
    t=x;
    x=y;
    y=t-a/b*y;
    return d;
}
int Lcm(int a,int b)
{
    int x,y;
    return a*b/ex_gcd(a,b,x,y);
}
int guass()
{
    int i,j,row,col;
    for(row=0,col=0;row<n&&col<m;row++,col++){
        for(i=row;i<n;i++)
            if(matrix[i][col])
                break;
        if(i==n){          //col列全为0
            row--;
            continue;
        }
        if(i!=row)
            for(j=0;j<=m;j++)
                swap(matrix[row][j],matrix[i][j]);   //交换两行
        for(i=row+1;i<n;i++){          
            if(matrix[i][col]){
                int lcm=Lcm(matrix[row][col],matrix[i][col]);
                int t1=lcm/matrix[i][col],t2=lcm/matrix[row][col];
                for(j=col;j<=m;j++)
                    matrix[i][j]=((matrix[i][j]*t1-matrix[row][j]*t2)%MOD+MOD)%MOD;
            }
        }
    }
    for(i=row;i<n;i++)     
        if(matrix[i][m])          //无解
            return -1;
    if(row<m)                    //有无穷解
        return 0;
    memset(ans,0,sizeof(ans));  //唯一解求解过程如下
    for(i=n-1;i>=0;i--){        
        int temp=0;
        for(j=i+1;j<m;j++)
            temp=(temp+matrix[i][j]*ans[j]%MOD)%MOD;
        int b=((matrix[i][m]-temp)%MOD+MOD)%MOD;
        int x,y;
        int d=ex_gcd(matrix[i][i],MOD,x,y);  //解模线性方程
        x=x*(b/d)%MOD;
        x=(x%(MOD/d)+(MOD/d))%(MOD/d);
        ans[i]=x;
        if(ans[i]<3)
            ans[i]+=7;
    }
    return 1;
}
int main()
{
    int num,i,j,type;
    char start[5],end[5];
    while(scanf("%d%d",&m,&n)!=EOF){
        if(m==0&&n==0)
            break;
        memset(matrix,0,sizeof(matrix));
        for(i=0;i<n;i++){
            scanf("%d%s%s",&num,start,end);
            matrix[i][m]=((get_id(end)-get_id(start)+1)%MOD+MOD)%MOD; //求生产时间对7取余
            for(j=1;j<=num;j++){
                scanf("%d",&type);
                matrix[i][type-1]=(matrix[i][type-1]+1)%MOD;   //记录矩阵的值
            }
        }
        int flag=guass();   //高斯消元
        if(flag==-1)
            printf("Inconsistent data.\n");
        else if(flag==0)
            printf("Multiple solutions.\n");
        else{
            for(i=0;i<m-1;i++)
                printf("%d ",ans[i]);
            printf("%d\n",ans[m-1]);
        }
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值