POJ 2947 Widget Factory(高斯消元解同余方程组)

97 篇文章 0 订阅
47 篇文章 0 订阅

传送门

Widget Factory
Time Limit: 7000MSMemory Limit: 65536K
Total Submissions: 5663Accepted: 1961

Description

The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to build a widget depends on its type: the simple widgets need only 3 days, but the most complex ones may need as many as 9 days.

The factory is currently in a state of complete chaos: recently, the factory has been bought by a new owner, and the new director has fired almost everyone. The new staff know almost nothing about building widgets, and it seems that no one remembers how many days are required to build each diofferent type of widget. This is very embarrassing when a client orders widgets and the factory cannot tell the client how many days are needed to produce the required goods. Fortunately, there are records that say for each widgeteer the date when he started working at the factory, the date when he was fired and what types of widgets he built. The problem is that the record does not say the exact date of starting and leaving the job, only the day of the week. Nevertheless, even this information might be helpful in certain cases: for example, if a widgeteer started working on a Tuesday, built a Type 41 widget, and was fired on a Friday,then we know that it takes 4 days to build a Type 41 widget. Your task is to figure out from these records (if possible) the number of days that are required to build the different types of widgets.

Input

The input contains several blocks of test cases. Each case begins with a line containing two integers: the number 1 ≤ n ≤ 300 of the different types, and the number 1 ≤ m ≤ 300 of the records. This line is followed by a description of the m records. Each record is described by two lines. The first line contains the total number 1 ≤ k ≤ 10000 of widgets built by this widgeteer, followed by the day of week when he/she started working and the day of the week he/she was fired. The days of the week are given bythe strings `MON’, `TUE’, `WED’, `THU’, `FRI’, `SAT’ and `SUN’. The second line contains k integers separated by spaces. These numbers are between 1 and n , and they describe the diofferent types of widgets that the widgeteer built. For example, the following two lines mean that the widgeteer started working on a Wednesday, built a Type 13 widget, a Type 18 widget, a Type 1 widget, again a Type 13 widget,and was fired on a Sunday.

4 WED SUN
13 18 1 13

Note that the widgeteers work 7 days a week, and they were working on every day between their first and last day at the factory (if you like weekends and holidays, then do not become a widgeteer!).

The input is terminated by a test case with n = m = 0 .

Output

For each test case, you have to output a single line containing n integers separated by spaces: the number of days required to build the different types of widgets. There should be no space before the first number or after the last number, and there should be exactly one space between two numbers. If there is more than one possible solution for the problem, then write `Multiple solutions.’ (without the quotes). If you are sure that there is no solution consistent with the input, then write `Inconsistent data.’(without the quotes).

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.

Hint

Huge input file, ‘scanf’ recommended to avoid TLE.

题目大意:

这个题目的意思还是很难懂的,大体上就是说:有一个工厂生产有 n 中不同的装饰品,每个装饰品的生产时间是 t(3t9) 天, 因为一些原因

这个工厂换了一个老板,而这个老板几乎将所有的员工都解散了,所以招来的这些新的员工不熟悉每个装饰品的生产时间,现在有 m 个条件,

让你根据这 m 个条件来推测出每个装饰品的生产时间:这 m 个时间的描述如下:

首先给了一个整数 p 和两个字符串 st end (星期几到星期几)表示的是在  st  end 内(可能有很多周)生产了 p

装饰品,第二行输入的是装饰品的种类 val[i],可能有相同的装饰品也就是存在 val[i] == val[j] 的情况。如果有唯一解的时候输出解,

没有解输出”Inconsistent data.”,有多解输出”Multiple solutions.”

解题思路:

首先我们可以根据题目大意,列出一系列的同余方程组:我们设每个装饰品的生产时间是 xi ,那么就有 n xi ,然后给定的 m 个条件

就是相当于有 m 个方程,假设生产第 i 类的商品有 ai 件,那么满足方程:

a0x0+a1x1+...+an1xn1 = (endst+1)MOD 7
….

会有 m 个这样的方程,然后根据高斯消元就可以解决了。

My Code

/**
2016 - 09 - 12 上午
Author: ITAK

Motto:

今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
**/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9+5;
const int MAXN = 400+5;
const int MOD = 7;
const double eps = 1e-7;
const double PI = acos(-1);
using namespace std;
LL Scan_LL()///输入外挂
{
    LL res=0,ch,flag=0;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
int Scan_Int()///输入外挂
{
    int res=0,ch,flag=0;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
void Out(LL a)///输出外挂
{
    if(a>9)
        Out(a/10);
    putchar(a%10+'0');
}
int equ, var;///equ个方程 var个变量
int a[MAXN][MAXN];///增广矩阵
int x[MAXN];///解集
int x_i[MAXN];
int free_x[MAXN];///判断是不是自由变元
int free_num;///自由变元的个数
inline int GCD(int m, int n)
{
    if(n == 0)
        return m;
    return GCD(n, m%n);
}
inline int LCM(int aa, int bb)
{
    return aa/GCD(aa,bb)*bb;
}
void Exgcd(int aa, int bb, int &xx, int &yy)
{
    if(bb == 0)
    {
        xx = 1;
        yy = 0;
        return;
    }
    int xx1, yy1;
    Exgcd(bb, aa%bb, xx1, yy1);
    xx = yy1;
    yy = xx1 - (aa/bb)*yy1;
}
void Debug()
{
    puts("");
    cout<<"+++++++++++++++++++++++++++分界线++++++++++++++++++++++++++++++"<<endl;
    for(int i=0; i<equ; i++)
    {
        for(int j=0; j<var+1; j++)
        {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<"+++++++++++++++++++++++++++分界线++++++++++++++++++++++++++++++"<<endl;
    puts("");
}
int Gauss()
{
    int Max_r;///当前列绝对值最大的存在的行
    ///col:处理当前的列
    int row,col = 0;
    int free_x_num;
    int free_index;
    free_num = 0;
    for(int i=0; i<=var; i++)
    {
        x[i] = 0;
        free_x[i] = 1;
    }
    for(row=0; row<equ&&col<var; row++,col++)
    {
        Max_r = row;
        for(int i=row+1; i<equ; i++)
            if(abs(a[i][col]) > abs(a[Max_r][col]))
                Max_r = i;
        if(a[Max_r][col] == 0)
        {
            free_x[col] = 1;
            x_i[free_num++] = col;
        }
        if(Max_r != row)
            for(int i=0; i<var+1; i++)
                swap(a[row][i], a[Max_r][i]);

        if(a[row][col] == 0)
        {
            row--;
            continue;
        }
        for(int i=row+1; i<equ; i++)
        {
            if(a[i][col])
            {
                int lcm = LCM(abs(a[i][col]), abs(a[row][col]));
                int tp1=lcm/abs(a[i][col]), tp2=lcm/abs(a[row][col]);
                if(a[row][col]*a[i][col] < 0)
                    tp2 = -tp2;
                for(int j=col; j<var+1; j++)
                    a[i][j] = ( (tp1*a[i][j]-tp2*a[row][j]) % MOD + MOD ) % MOD;
            }
        }
    }
    for(int i=row; i<equ; i++)
        if(a[i][col])
            return -1;///无解
    if(row < var)
        return var - row;///自由变元的个数
    ///回代
    for(int i=var-1; i>=0; i--)
    {
        int tmp = a[i][var] % MOD;
        for(int j=i+1; j<var; j++)
            if (a[i][j])
                tmp = ((tmp - a[i][j]*x[j]) % MOD + MOD) % MOD;
        while(tmp % a[i][i])
            tmp += MOD;
        x[i] = (tmp/a[i][i]) % MOD;
        if(x[i] < 3)
            x[i] += MOD;
    }
    return 0;///唯一解
}

char st[20], end1[20];
int Solve1(char str[])
{
    if(strcmp(str, "MON") == 0)
        return 1;
    if(strcmp(str, "TUE") == 0)
        return 2;
    if(strcmp(str, "WED") == 0)
        return 3;
    if(strcmp(str, "THU") == 0)
        return 4;
    if(strcmp(str, "FRI") == 0)
        return 5;
    if(strcmp(str, "SAT") == 0)
        return 6;
    if(strcmp(str, "SUN") == 0)
        return 7;
}

int main()
{
    int n, m;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0 && m==0)
            break;
        equ = m;
        var = n;
        memset(a, 0, sizeof(a));
        memset(x, 0, sizeof(x));
        for(int i=0; i<m; i++)
        {
            int k;
            scanf("%d%s%s",&k,st,end1);
            a[i][var] = (Solve1(end1)-Solve1(st)+8) % MOD;
            a[i][var] = (a[i][var] % MOD + MOD) % MOD;
            for(int j=0; j<k; j++)
            {
                int val;
                scanf("%d",&val);
                a[i][val-1]++;
                a[i][val-1] %= MOD;
            }
        }
        int tmp = Gauss();
        ///Debug();
        if(tmp == -1)
            puts("Inconsistent data.");
        else if(tmp > 0)
            puts("Multiple solutions.");
        else
        {
            for(int i=0; i<var; i++)
            {
                if(i == var-1)
                    printf("%d\n",x[i]);
                else
                    printf("%d ",x[i]);
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值