zoukankan      html  css  js  c++  java
  • poj 2947 Widget Factory(高斯消元 模线性方程)

    题目链接:http://poj.org/problem?id=2947

    大致题意:产品制造者制造型号不同的产品所需的时间是不同的(规定为3~9天),现在已知生产产品的的种数N和工作者的人数M,告诉你每个工作者是从星期几开始工作,星期几结束的(可能隔着n周),这个工作者生产了K件产品,产品的型号分别是多少。根据以上信息,求是否可以求出这N中产品的具体生产所需时间(无解 一解 多解),有解输出解,无解和多解输出相应信息。

    Time Limit: 7000MSMemory Limit: 65536K

    样例:

    Sample Input

    2 3
    2 MON THU
    1 2
    3 MON FRI
    1 1 2
    3 MON SUN
    1 2 2
    10 2
    1 MON TUE 
    3
    1 MON WED
    3
    0 0

    Sample Output

    8 3
    Inconsistent data.

    思路:比较典型的求解线性方程组的解的题目,n种产品对应n个未知量,m个工作者对应m个方程,每个方程的解为(END_DAY - START_DAY + 1 +7) mod 7。这个题简单在对7取模,7是素数,每个模线性方程对应唯一解。所以如果对应的方程组有一解,则对应的模线性方程中的未知量也只有一解。方程组多解时,模线性方程也不可能出现无解的情况,所以也是多解,无解同理肯定对应无解。

    高斯消元的几个步骤:1.选主元(选最大为主元以减少误差) 2.向下消元 3.根据方程组最后的形式判断解的情况(出现系数全为0最后一位非0的是无解,有多余全0行则多解,严格三角阵为一解)。判断解的顺序是: 无解 - > 多解 - > 一解(非整数解 - > 整数解)

    对于最后求模线性方程的解,由于答案就在3~9之间,枚举比较简单,扩展GCD和求乘法逆元都相对较麻烦。

    最后注意矩阵进行累加,消项等运算时要时刻对7取模,否则容易超出范围。

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<cstring>
      4 const int MAXNUM=305;
      5 char date[7][5]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
      6 int fun[MAXNUM][MAXNUM];
      7 int res[MAXNUM];
      8 int n,m;
      9 int gcd(int a,int b){
     10     if(b==0){
     11         return a;
     12     }
     13     return gcd(b,a%b);
     14 }
     15 
     16 int lcm(int a,int b){
     17     return a*b/gcd(a,b);
     18 }
     19 int gauss(){
     20     int i,j,k,max,col=0;
     21     for(k=0;k<m&&col<n;k++,col++){  //枚举第K行,第col列
     22         max=k;
     23         for(i=k+1;i<m;i++){  //选第k行后的所有行中第col列最大的那一行做主元
     24             if(fabs(fun[i][col])>fabs(fun[max][col])){
     25                 max=i;
     26             }
     27         }
     28         if(max!=k){//交换行
     29             for(j=k;j<=n;j++){
     30                 int temp=fun[k][j];
     31                 fun[k][j]=fun[max][j];
     32                 fun[max][j]=temp;
     33             }
     34         }
     35         if(fun[k][col]==0){  //如果第col列已经是0,那么继续枚举第k行第col+1列
     36             k--;
     37             continue;
     38         }
     39         for(i=k+1;i<m;i++){  //向下消元
     40             if(fun[i][col]!=0){
     41                 int LCM=lcm(fun[i][col],fun[k][col]);
     42                 int ta=LCM/fun[i][col];
     43                 int tb=LCM/fun[k][col];
     44                 for(j=col;j<=n;j++){
     45                     fun[i][j]=((fun[i][j]*ta-fun[k][j]*tb)%7+7)%7;
     46                 }
     47             }
     48         }
     49     }
     50     for(i=k;i<m;i++){  //判断无解
     51         if(fun[i][n]!=0)return -1;
     52     }
     53     if(k<n)return 0;  //最后k的值是非自由元的个数,k<n为多解
     54     for(i=n-1;i>=0;i--){  //一解时自下而上回带求解(上三角)
     55         for(j=i+1;j<n;j++){
     56             fun[i][n]=((fun[i][n]-fun[i][j]*res[j])%7+7)%7;
     57         }
     58         for(j=3;j<=9;j++){
     59             if((j*fun[i][i])%7==fun[i][n]){
     60                 res[i]=j;break;
     61             }
     62         }
     63     }
     64     return 1; 
     65 }
     66 int main(){
     67     int i,j,cnt,pos1,pos2,temp;
     68     char c1[5],c2[5];
     69     while(scanf("%d%d",&n,&m)&&(m||n)){
     70         memset(fun,0,sizeof(fun));
     71         for(j=0;j<m;j++){
     72             scanf("%d %s %s",&cnt,c1,c2);
     73             for(i=0;i<7;i++){
     74                 if(strcmp(c1,date[i])==0){
     75                     pos1=i;
     76                 }
     77                 if(strcmp(c2,date[i])==0){
     78                     pos2=i;
     79                 }
     80             }
     81             fun[j][n]=pos2-pos1+1+7;
     82             for(i=0;i<cnt;i++){
     83                 scanf("%d",&temp);
     84                 fun[j][temp-1]++;
     85             }
     86             for(i=0;i<=n;i++)fun[j][i]%=7;
     87         }
     88         int ans=gauss();
     89         if(ans==-1){
     90             printf("Inconsistent data.\n");
     91         }
     92         else if(ans==0){
     93             printf("Multiple solutions.\n");
     94         }
     95         else if(ans==1){
     96             
     97             for(i=0;i<n-1;i++){
     98                 printf("%d ",res[i]);
     99             }
    100             printf("%d",res[n-1]);
    101             printf("\n");
    102         }
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    WM有约(二):配置信息
    ASP+Wrod、excel打印程序示例
    用stream直接下载文件
    ASP判断gif图像尺寸的方法
    白菜世纪RSS无刷新聚合器(1221修正)
    ASP.NET常用代码
    图片超过规定的大小就按原图片大小缩小
    javascript弹出窗口总结
    asp excel sql 关系大总结
    打开窗口
  • 原文地址:https://www.cnblogs.com/mcflurry/p/2614701.html
Copyright © 2011-2022 走看看