题目链接: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,则可以列出下列方程:
a1*x1+a2*x2+...an*xn = b (mod 7);
这样一共可以列出m 个方程式,然后使用高斯消元来解此方程组即可。
实现代码如下:
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int inf=0x3fffffff; const int maxn=300; int a[maxn][maxn+1],x[maxn];//a是系数矩阵和增广矩阵,x存放最后的解 int equ,var,free_n;//equ是系数矩阵的行数,var个变元(即系数矩阵的列数) void Debug() { for(int i=0;i<equ;i++) { for(int j=0;j<var+1;j++) cout<<a[i][j]<<" "; cout<<endl; } } int exc(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 return 7; } void Init() { int p,d; char s1[5],s2[5]; memset(a,0,sizeof(a)); memset(x,0,sizeof(x)); for(int i=0;i<equ;i++) { scanf("%d%s%s",&p,s1,s2); a[i][var]=( ( exc(s2)-exc(s1) )%7+8 )%7; for(int j=0;j<p;j++) { scanf("%d",&d); a[i][d-1]++; //题中类别由1到n,故需要减1 a[i][d-1]%=7; } } } int min(int a,int b) { return a<b?a:b; } int gcd(int a,int b) { if(a<0) return gcd(-a,b); if(b<0) return gcd(a,-b); return b==0?a:gcd(b,a%b); } int ex_gcd(int a,int b,int &x,int &y) { if(b==0) { x=1,y=0; return a; } int ret=ex_gcd(b,a%b,x,y); int tmp=x; x=y; y=tmp-a/b*y; return ret; } void Gauss() { int k,col=0; //当前处理的列 for(k=0;k<equ&&col<var;k++,col++) { int mx=k; for(int i=k+1;i<equ;i++) if(a[i][col]>a[mx][col]) mx=i; if(mx!=k) for(int i=k;i<var+1;i++) swap(a[k][i],a[mx][i]); if(!a[k][col]) { k--; continue; } for(int i=k+1;i<equ;i++) if(a[i][col]!=0) { int lcm=a[k][col] / gcd(a[k][col],a[i][col]) * a[i][col]; int ta=lcm/a[i][col], tb=lcm/a[k][col]; if(a[i][col]*a[k][col]<0) tb=-tb; for(int j=col;j<var+1;j++) a[i][j]=( (a[i][j]*ta)%7 - (a[k][j]*tb)%7 +7 )%7; } } //Debug(); for(int i=k;i<equ;i++) if(a[i][col]!=0) { puts("Inconsistent data."); return ; } if(k<var) { puts("Multiple solutions."); return ; } for(int i=0,j;i<equ;i++) //每一行主元素化为非零 if(!a[i][i]) { for(j=i+1;j<var;j++) if(a[i][j]) break; if(var<=j) break; for(int r=0;r<equ;r++) swap(a[r][i],a[r][j]); } for(int i=k-1;i>=0;i--) { int tmp=a[i][var]%7,x1,y; for(int j=i+1;j<var;j++) if(a[i][j]) tmp=((tmp-x[j]*a[i][j])%7+7)%7; int gcd=ex_gcd(a[i][i],7,x1,y); x[i]=(x1*tmp/gcd%7+7)%7; } for(int i=0;i<var;i++) if(x[i]<3) x[i]+=7; printf("%d",x[0]); for(int i=1;i<var;i++) printf(" %d",x[i]); puts(""); } int main() { while(scanf("%d%d",&var,&equ)) { if(var==0&&equ==0) break; Init(); Gauss(); } return 0; }