zoukankan      html  css  js  c++  java
  • poj2947(高斯消元解同模方程组)

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

    题意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下:

    p start end
    a1, a2......ap (1<= ai <= n)
    第一行表示从星期 start 到星期 end 一共生产了p 件装饰物 (工作的天数为end - start + 1 + 7*x, 加 7*x 是因为它可能生产很多周),第二行表示这 p 件装饰物的种类(可能出现相同的种类,即 ai = aj)。规定每件装饰物至少生产3 天,最多生产9 天。问每种装饰物需要生产的天数。如果没有解,则输出“Inconsistent data.”,如果有多解,则输出“Multiple solutions.”,如果只有唯一解,则输出每种装饰物需要生产的天数。
     
    思路:高斯消元接同模方程组
    设每种装饰物需要生产的天数为 xi(1<=i<=n)。每一个条件就相当于给定了一个方程式,假设生产1 类装饰物 a1 件、2 类装饰物 a2 件、i 类装饰物 ai 件所花费的天数为 b = end - star + 1 + 7 * x,则可以列出下列方程:
    a1 * x1 + a2 * x2 +...an * xn = b (mod 7)
    这样一共可以列出m 个方程式,然后使用高斯消元来解此方程组即可。
     
     
    代码:
      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <algorithm>
      4 #include <string.h>
      5 #include <math.h>
      6 using namespace std;
      7 
      8 const int MAXN = 4e2;
      9 const int mod = 7;
     10 bool free_x[MAXN];
     11 int a[MAXN][MAXN];
     12 int x[MAXN];
     13 
     14 inline int gcd(int a, int b){
     15     int t;
     16     while(b != 0){
     17         t = b;
     18         b = a % b;
     19         a = t;
     20     }
     21     return a;
     22 }
     23 
     24 inline int lcm(int a, int b){
     25     return a / gcd(a, b) * b;
     26 }
     27 
     28 //返回-1表示无解,0表示有唯一解,大于0表示无穷解并返回变元个数
     29 int Gauss(int equ, int var){//equ为方程数,var为未知数个数
     30     int i, j, k;
     31     int max_r;//当前列绝对值最大的行
     32     int col;//当前处理的列
     33     int ta, tb;
     34     int LCM;
     35     int temp;
     36     int free_x_num;
     37     int free_index;
     38     for(int i = 0; i <= var; i++){
     39         x[i] = 0;
     40         free_x[i] = true;//初始化全部为变元
     41     }
     42     for(k = 0, col = 0; k < equ && col < var; k++, col++){
     43         //枚举当前处理的行k
     44         //找到当前col列元素绝对值最大的行与第k行交换
     45         max_r = k;
     46         for(i = k + 1; i < equ; i++){
     47             if(abs(a[i][col] > abs(a[max_r][col]))) max_r = i;//记录当前列中最大值所在行
     48         }
     49         if(max_r != k){//与第k行交换
     50             for(int j = k; j < var + 1; j++){
     51                 swap(a[k][j], a[max_r][j]);
     52             }
     53         }
     54         if(a[k][col] == 0){//说明col列中第k行以下全是0了,则处理当前下一行
     55             k--;
     56             continue;
     57         }
     58         for(i = k + 1; i < equ; i++){//枚举要删去的行
     59             if(a[i][col] != 0){
     60                 LCM = lcm(abs(a[i][col]), abs(a[k][col]));
     61                 ta = LCM / abs(a[i][col]);
     62                 tb = LCM / abs(a[k][col]);
     63                 if(a[i][col] * a[k][col] < 0) tb = -tb;
     64                 for(j = col; j < var + 1; j++){
     65                     a[i][j] = ((a[i][j] * ta - a[k][j] * tb) % mod + mod) % mod;
     66                 }
     67             }
     68         }
     69     }
     70     //无解的情况,化简的增广矩阵中存在(0,0,...1)这样的行(a!=0)
     71     for(i = k; i < equ; i++){
     72         if(a[i][col] != 0) return -1;
     73     }
     74     //无穷解的情况: 在var * (var + 1)的增广阵中出现(0, 0, ..., 0)这样的行,即说明没有形成严格的上三角阵.
     75     //且出现的行数即为自由变元的个数.
     76     if(k < var){
     77         for(i = k - 1; i >= 0; i--){
     78             // 第i行一定不会是(0, 0, ..., 0)的情况,因为这样的行是在第k行到第equ行.
     79             // 同样,第i行一定不会是(0, 0, ..., a), a != 0的情况,这样的无解的.
     80             free_x_num = 0;//用于判断该行中的不确定的变元的个数,如果超过1个,则无法求解,它们仍然为不确定的变元.
     81             for(j = 0; j < var; j++){
     82                 if(a[i][j] && free_x[j]) free_x_num++, free_index = j;
     83             }
     84             if(free_x_num > 1) continue;//无法求解出确定的变元
     85             // 说明就只有一个不确定的变元free_index,那么可以求解出该变元,且该变元是确定的
     86             temp = a[i][var];
     87             for(j = 0; j < var; j++){
     88                 if(a[i][j] != 0 && j != free_index) temp -= a[i][j] * x[j] % mod;
     89                 temp = (temp % mod + mod) % mod;
     90             }
     91             x[free_index] = (temp / a[i][free_index]) % mod;//求出该变元
     92             free_x[free_index] = 0;//该变元已经确定,取消对应变元标记
     93         }
     94         return var - k;//自由变元有var-k个
     95     }
     96     //唯一解的情况: 在var * (var + 1)的增广阵中形成严格的上三角阵.
     97     //计算出Xn-1, Xn-2 ... X0.
     98     for(i = var - 1; i >= 0; i--){
     99         temp = a[i][var];
    100         for(j = i + 1; j < var; j++){
    101             if(a[i][j] != 0) temp -= a[i][j] * x[j];
    102             temp = (temp % mod + mod) % mod;
    103         }
    104         while(temp % a[i][i] != 0) temp += mod;
    105         x[i] = (temp /a[i][i]) % mod;
    106     }
    107     return 0;
    108 }
    109 
    110 int tran(char *s){
    111     if(strcmp(s, "MON") == 0) return 1;
    112     if(strcmp(s, "TUE") == 0) return 2;
    113     if(strcmp(s, "WED") == 0) return 3;
    114     if(strcmp(s, "THU") == 0) return 4;
    115     if(strcmp(s, "FRI") == 0) return 5;
    116     if(strcmp(s, "SAT") == 0) return 6;
    117     return 7;
    118 }
    119 
    120 char s1[20], s2[20];
    121 
    122 int main(void){
    123     int n, m, k, t;
    124     while(~scanf("%d%d", &n, &m)){
    125         if(n + m == 0) break;
    126         memset(a, 0, sizeof(a));
    127         for(int i = 0; i < m; i++){
    128             scanf("%d%s%s", &k, s1, s2);
    129             a[i][n] = ((tran(s2) - tran(s1) + 1) % mod + mod) % mod;//方程组的常数项
    130             while(k--){
    131                 scanf("%d", &t);
    132                 t--;
    133                 a[i][t]++;
    134                 if(a[i][t] >= mod) a[i][t] %= mod;
    135             }
    136         }
    137         int cnt = Gauss(m, n);//m为条件数目即方程数
    138         if(cnt == 0){
    139             for(int i = 0; i < n; i++){
    140                 if(x[i] <= 2) x[i] += 7;//题意要求每件物品最少生产3天,最多生产9天
    141                 printf("%d ", x[i]);
    142             }
    143             puts("");
    144         }else if(cnt == -1) puts("Inconsistent data.");
    145         else puts("Multiple solutions.");
    146     }
    147     return 0;
    148 }
    View Code
  • 相关阅读:
    系统数据库如何恢复Master数据库
    在Orderby子句中使用CASE 语句
    SQL NOTECURSOR
    MVC 中静态文件部分动态化
    SQL NOTCTE
    Get data style from Excel
    SQL NOTPARTITION
    LAMDA表达式学习
    SQL NOTEVARIABLE
    起II6.0中使用windows2003自带的虚拟主机管理系统
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7581875.html
Copyright © 2011-2022 走看看