您的位置:首页 > 其它

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

2013-02-10 02:19 302 查看
题意:N种物品,M条记录,接写来M行,每行有K,str1,str2,表示第i个记录从星期str1到星期str2,做了K件物品,接下来的K个数为物品的编号。求做每个物品所需的时间,并且最后结果在3-9之间

很容易想到高斯消元。但是是带同余方程的高斯消元,开始建立关系的时候就要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;

但其实这道题用扩展gcd真的大材小用了,因为模数是固定的而且很小就是7,所以直接枚举试就可以了~~

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
using namespace std;
typedef long long LL;

int gcd(int a, int b){
return b ? gcd(b, a%b) : a;
}
int lcm(int a, int b){
return a / gcd(a,b) * b;
}
const int MAX_EQU = 310;
typedef struct  equation_set{
int equ, var;               	//方程个数、变元个数,则增广矩阵有equ行、var+1列.
int mat[MAX_EQU][MAX_EQU+1];  	//增广矩阵
int x[MAX_EQU];            	 	//方程解向量
bool free_x[MAX_EQU];       	//判断是否是不确定变元

void init(int in_equ, int in_var);
void debug();
int gauss();
}EQU;
void equation_set::init(int in_equ, int in_var){
equ = in_equ;
var = in_var;

memset(mat, 0, sizeof(mat));
memset(x, 0, sizeof(x));
memset(free_x, 1, sizeof(free_x));
}
void equation_set::debug(){
for (int i = 0; i < equ; i ++){
for (int j = 0; j < var; j ++)
cout << mat[i][j] << " ";
cout << mat[i][var] << endl;
}
}
int equation_set::gauss(){
int row = 0, col = 0;
int max_row;
while (row < equ && col < var){
max_row = row;
for (int i = row + 1; i < equ; i ++)
if (abs(mat[i][col]) > abs(mat[max_row][col]))
max_row = i;
if (max_row != row){
for (int j = 0; j <= var; j ++){
int tmp = mat[row][j];
mat[row][j] = mat[max_row][j];
mat[max_row][j] = tmp;
}
}
if (mat[row][col] == 0){
col ++;
continue;
}
//普通方程组行阶梯化:
for (int i = row + 1; i < equ; i ++){
if (mat[i][col] != 0){
int LCM = lcm(abs(mat[i][col]), abs(mat[row][col]));
int ta = LCM  / abs(mat[i][col]), tb = LCM / abs(mat[row][col]);
if (mat[i][col] * mat[row][col] < 0)    tb = -tb;
for (int j = 0; j <= var; j ++)
mat[i][j] = ((mat[i][j] * ta - mat[row][j] * tb) % 7 + 7) % 7;
}
}

row++, col++;
}
//debug();

//1. 无解
for (int i = row; i < equ; i++){
if (mat[i][col] != 0) return -1;
}
//2.无穷解(这里只是计算出了确定变元,对于多解的计算,需要枚举自由变元的状态或者其他方法求解.)
if (row < var){
return 1;
}
//3.唯一解
for (int i = row - 1; i >= 0; i --){
int tmp = (mat[i][var] % 7 + 7) % 7;
for (int j = var - 1; j > i; j --)
tmp = ((tmp - x[j] * mat[i][j]) % 7 + 7) % 7;
while(tmp % mat[i][i] != 0)
tmp += 7;
x[i] = (tmp / mat[i][i] % 7 + 7) % 7;
}
return 0;
}
int week(char s[]){
if (strcmp(s, "MON") == 0)
return 1;
else if (strcmp(s, "TUE") == 0)
return 2;
else if (strcmp(s, "WED") == 0)
return 3;
else if (strcmp(s, "THU") == 0)
return 4;
else if (strcmp(s, "FRI") == 0)
return 5;
else if (strcmp(s, "SAT") == 0)
return 6;
else if (strcmp(s, "SUN") == 0)
return 7;
}
int main(){
int n,m;
while(scanf("%d%d", &n, &m) == 2){
if (n + m == 0)
break;
EQU E;
E.init(m, n);
for (int i = 0; i < m; i ++){
int k;
char s1[10], s2[10];
scanf("%d", &k);
scanf("%s%s", s1, s2);
E.mat[i]
= (week(s2) - week(s1) + 1) % 7;
for (int j = 0; j < k; j ++){
int tmp;
scanf("%d", &tmp);
E.mat[i][tmp-1] ++;
}
for (int j = 0; j < n; j ++)
E.mat[i][j] %= 7;
}
//E.debug();
int p = E.gauss();
if (p == -1){
printf("Inconsistent data.\n");
}
else if (p == 1){
printf("Multiple solutions.\n");
}
else{
for (int i = 0; i < n; i ++)
if(E.x[i] < 3)
E.x[i] += 7;
for (int i = 0; i < n - 1; i ++)
printf("%d ", E.x[i]);
printf("%d\n", E.x[n-1]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: