POJ_1166_The Clocks

来源:互联网 发布:嵌入式linux书 编辑:程序博客网 时间:2024/06/09 16:54
The Clocks
Time Limit: 1000MS
Memory Limit: 65536KTotal Submissions: 17602
Accepted: 7217

Description

|-------|    |-------|    |-------||       |    |       |    |   |   ||---O   |    |---O   |    |   O   ||       |    |       |    |       ||-------|    |-------|    |-------|    A            B            C    |-------|    |-------|    |-------||       |    |       |    |       ||   O   |    |   O   |    |   O   ||   |   |    |   |   |    |   |   ||-------|    |-------|    |-------|    D            E            F    |-------|    |-------|    |-------||       |    |       |    |       ||   O   |    |   O---|    |   O   ||   |   |    |       |    |   |   ||-------|    |-------|    |-------|    G            H            I    (Figure 1)

There are nine clocks in a 3*3 array (figure 1). The goal is to return all the dials to 12 o'clock with as few moves as possible. There are nine different allowed ways to turn the dials on the clocks. Each such way is called a move. Select for each move a number 1 to 9. That number will turn the dials 90' (degrees) clockwise on those clocks which are affected according to figure 2 below. 
Move   Affected clocks  1         ABDE 2         ABC 3         BCEF 4         ADG 5         BDEFH 6         CFI 7         DEGH 8         GHI 9         EFHI       (Figure 2)

Input

Your program is to read from standard input. Nine numbers give the start positions of the dials. 0=12 o'clock, 1=3 o'clock, 2=6 o'clock, 3=9 o'clock.

Output

Your program is to write to standard output. Output a shortest sorted sequence of moves (numbers), which returns all the dials to 12 o'clock. You are convinced that the answer is unique.

Sample Input

3 3 02 2 22 1 2

Sample Output

4 5 8 9

Source

IOI 1994

  • 矩阵大法好!!!简洁易懂容易错QAQ,小错误不停好吧~
  • 恩,开始说人话
  • 首先看题是给出开始状态和结束状态以及操作方式,并保证有唯一解
  • 自然联想到方程求解
  • 我们令:
  • 开始矩阵  S(n,1)
  • 结束矩阵  E(n,1)
  • 转移距离  T(n,1)
  • 相互关系  R(n,n)
  • 操作次数  X(n,1)
  • 根据题意我们不难得出以下式子:
  • S + R*X = E ;T = E - S ;R*X = T ;
  • 我们知道开始状态通过全部的操作方式后对4取模计数可以到达结束状态
  • 操作的前后顺序对于最终结果没有影响
  • 在最后输出答案时按照操作标号从小到大顺序逐个按计数输出即可
  • 而且根据时钟是模运算的性质,每种操作至多3次,到4次时就是一次循环了
  • 那么现在是时候考虑解方程的问题了,看起来用逆矩阵好些
  • 下面这个是相互关系矩阵
  • int R[mxx][mxx]={//    1, 2, 3, 4, 5, 6, 7, 8, 9{ 1, 1, 0, 1, 0, 0, 0, 0, 0},// A{ 1, 1, 1, 0, 1, 0, 0, 0, 0},// B{ 0, 1, 1, 0, 0, 1, 0, 0, 0},// C{ 1, 0, 0, 1, 1, 0, 1, 0, 0},// D{ 1, 0, 1, 0, 1, 0, 1, 0, 1},// E{ 0, 0, 1, 0, 1, 1, 0, 0, 1},// F{ 0, 0, 0, 1, 0, 0, 1, 1, 0},// G{ 0, 0, 0, 0, 1, 0, 1, 1, 1},// H{ 0, 0, 0, 0, 0, 1, 0, 1, 1}// I};
  • 那么它的逆矩阵如下:
  • double A[mxx][mxx]={{-0.2, 0.4,-0.2, 0.4, 0.4,-0.6,-0.2,-0.6, 0.8},{ 0.6,-0.2, 0.6,-0.2,-0.2,-0.2,-0.4, 0.8,-0.4},{-0.2, 0.4,-0.2,-0.6, 0.4, 0.4, 0.8,-0.6,-0.2},{ 0.6,-0.2,-0.4,-0.2,-0.2, 0.8, 0.6,-0.2,-0.4},{-0.2, 0.4,-0.2, 0.4,-0.6, 0.4,-0.2, 0.4,-0.2},{-0.4,-0.2, 0.6, 0.8,-0.2,-0.2,-0.4,-0.2, 0.6},{-0.2,-0.6, 0.8, 0.4, 0.4,-0.6,-0.2, 0.4,-0.2},{-0.4, 0.8,-0.4,-0.2,-0.2,-0.2, 0.6,-0.2, 0.6},{ 0.8,-0.6,-0.2,-0.6, 0.4, 0.4,-0.2, 0.4,-0.2}};
  • 恩,一看画风就不一样,但是用这个逆矩阵的话,样例是真的能过!!!
  • 我们这个时候回来看看题,要求是模4计数,所以在求解方程的时候要对系数进行对4取模
  • 所以我们要求的是对4取模的逆矩阵!!!
  • 若模m的n阶矩阵A的行列式|A|=k(mod m),且(k,m)=1,则A可以经一系列初等变换化成单位矩阵I
  • 这里|R|==5,(5,4)=1,满足条件
  • 具体参考关于模m矩阵的逆矩阵
  • int B[mxx][mxx]={{3, 2, 3, 2, 2, 1, 3, 1, 0},{3, 3, 3, 3, 3, 3, 2, 0, 2},{3, 2, 3, 1, 2, 2, 0, 1, 3},{3, 3, 2, 3, 3, 0, 3, 3, 2},{3, 2, 3, 2, 1, 2, 3, 2, 3},{2, 3, 3, 0, 3, 3, 2, 3, 3},{3, 1, 0, 2, 2, 1, 3, 2, 3},{2, 0, 2, 3, 3, 3, 3, 3, 3},{0, 1, 3, 1, 2, 2, 3, 2, 3}};
  • 求对n取模的逆矩阵的话,使得a[i][i]==1的操作和普通矩阵不一样,是要求解  ax=1(modn)的同余方程
  • 然后把解x乘到该行,之后对n取模,达到 a[i][i]==1 的目的
  • 其他的和高斯消元求解逆矩阵的过程是一样的
  • 当然了,鉴于这题数据规模小,很多人爆搜A了
  • 我只能说可能他们少了次练习或学习对n取模逆矩阵姿势的机会吧~
#include <iostream>#include <string>#include <cstdio>#include <cstring>#include <algorithm>#include <climits>#include <cmath>#include <vector>#include <queue>#include <stack>#include <set>#include <map>using namespace std;typedef long long           LL ;typedef unsigned long long ULL ;const int    maxn = 1000 + 10  ;const int    inf  = 0x3f3f3f3f ;const int    npos = -1         ;const int    mod  = 4          ;const int    mxx  = 100 + 5    ;const double eps  = 1e-6       ;inline int gcd(int x, int y){return y?gcd(y,x%y):x;}inline int gcd_driver(int x, int y){return gcd(max(abs(x),abs(y)),min(abs(x),abs(y)));}inline int extgcd(int a, int b, int &x, int &y){if(0==b){x=1;y=0;return a;}else{int r=extgcd(b,a%b,y,x);y-=x*(a/b);return r;}}inline int lcm(int x, int y){return abs(x*y)/gcd_driver(x,y);}inline int mod_equ(int a, int b, int n){int x, y;int d=extgcd(a,n,x,y);if(0==b%d){x=((x%n)+n)%n;return x*(b/d)%(n/d);}else{return -1;}}struct Matrix{int n;int a[mxx][mxx];void reset(int x){n=x;memset(a,0,sizeof(a));}Matrix operator * (const Matrix &X){Matrix Y;Y.reset(n);for(int k=0;k<n;k++)for(int i=0;i<n;i++)if(a[i][k])for(int j=0;j<n;j++)if(X.a[k][j])Y.a[i][j]=((Y.a[i][j] + (a[i][k]*X.a[k][j])%mod)%mod + 2*mod)%mod;return Y;}};Matrix inverse_mod(Matrix A){int n=A.n;Matrix C;C.reset(n);for(int i=0;i<n;i++)C.a[i][i]=1;for(int i=0;i<n;i++){for(int j=i;j<n;j++)if(1==gcd(A.a[j][i],mod)){if(j!=i)for(int k=0;k<n;k++){swap(A.a[i][k],A.a[j][k]);swap(C.a[i][k],C.a[j][k]);}break;}int t=mod_equ(A.a[i][i],1,mod);for(int k=0;k<n;k++){C.a[i][k]=((C.a[i][k]*t)%mod + 2*mod)%mod;A.a[i][k]=((A.a[i][k]*t)%mod + 2*mod)%mod;}for(int j=0;j<n;j++)if(j!=i && A.a[j][i]){t=A.a[j][i];for(int k=0;k<n;k++){C.a[j][k]=((C.a[j][k]-(C.a[i][k]*t)%mod)%mod + 2*mod)%mod;A.a[j][k]=((A.a[j][k]-(A.a[i][k]*t)%mod)%mod + 2*mod)%mod;}}}return C;}int n=9, f[mxx];int e[mxx][mxx]={//    1, 2, 3, 4, 5, 6, 7, 8, 9{ 1, 1, 0, 1, 0, 0, 0, 0, 0},// A{ 1, 1, 1, 0, 1, 0, 0, 0, 0},// B{ 0, 1, 1, 0, 0, 1, 0, 0, 0},// C{ 1, 0, 0, 1, 1, 0, 1, 0, 0},// D{ 1, 0, 1, 0, 1, 0, 1, 0, 1},// E{ 0, 0, 1, 0, 1, 1, 0, 0, 1},// F{ 0, 0, 0, 1, 0, 0, 1, 1, 0},// G{ 0, 0, 0, 0, 1, 0, 1, 1, 1},// H{ 0, 0, 0, 0, 0, 1, 0, 1, 1}// I};Matrix R, A, B, T;int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout);R.reset(n);for(int i=0;i<n;i++)for(int j=0;j<n;j++)R.a[i][j]=e[i][j];A=inverse_mod(R);while(~scanf("%d %d %d %d %d %d %d %d %d",&f[0],&f[1],&f[2],&f[3],&f[4],&f[5],&f[6],&f[7],&f[8])){T.reset(n);for(int i=0;i<n;i++)T.a[i][0]=(0-f[i]+mod)%mod;B=A*T;for(int i=0, output=0;i<n;i++)if(B.a[i][0]%mod){int t=B.a[i][0]%mod;if(!output){output=1;printf("%d",i+1);for(int j=1;j<t;j++)printf(" %d",i+1);}else{for(int j=0;j<t;j++)printf(" %d",i+1);}}printf("\n");}return 0;}


原创粉丝点击