poj_1166 The Clocks(高斯消元)

The Clocks
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 16797   Accepted: 6939

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 0
2 2 2
2 1 2

Sample Output

4 5 8 9
 
  
设C为当前操作的时钟状态(取值0~3),Xi为执行movei的次数,ai为movei是否能操作当前时钟,能为1,不能为0。
可得方程:(C + a1*X1 + a2*X2 + ... + a9*X9)mod4 = 0
即 (a1*X1 + a2*X2 + ... + a9*X9)mod4 = (4-C)mod4。
然后高斯消元求解。
-------------------------------
消元的时候如果选择绝对值最大的那一列就会wa,原因思考了一下,
如果我们的数据是 
0 0 0
0 0 0
0 0 2
那么选择最大值与不选最大值得出的结果是不一样的。
我们观察他们的最终矩阵
选最大值:
1 1 0 1 0 0 0 0 0 0
0 3 0 0 1 0 1 0 0 0
0 0 3 0 3 3 3 0 0 0
0 0 0 1 0 1 1 0 0 0
0 0 0 0 1 0 0 0 3 0
0 0 0 0 0 3 0 1 0 0
0 0 0 0 0 0 1 0 3 0
0 0 0 0 0 0 0 2 3 2
0 0 0 0 0 0 0 0 3 2
不选最大值:
1 1 0 1 0 0 0 0 0 0
0 1 1 0 0 1 0 0 0 0
0 0 1 3 1 0 0 0 0 0
0 0 0 1 0 1 1 0 0 0
0 0 0 0 3 0 0 0 1 0
0 0 0 0 0 3 0 1 0 0
0 0 0 0 0 0 3 0 1 0
0 0 0 0 0 0 0 3 1 0
0 0 0 0 0 0 0 0 3 2
可以发现不选最大值的矩阵中A[i][i]刚好都为1或3,而选最大值的矩阵中出现了一个A[7][7]=2。
可这道题所取的模为4,这样的话,由于我们消元与最终求解时都需要用到A[i][i],所以当有A[i][i]=2时我们并不能保证最终结果是正确的。
因为已知p是素数时,模p剩余系里每个除0以外的元素都有唯一的逆,但p不为素数时,比如这道题的模4,2就没有逆。
所以其实选最大值时跳过2也可以过。
 
  
 
  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define FOP freopen("data.txt","r",stdin)
#define FOP2 freopen("data1.txt","w",stdout)
#define inf 0x3f3f3f3f
#define maxn 310
#define mod 4
#define PI acos(-1.0)
#define LL long long
using namespace std;

typedef int Matrix[maxn][maxn];
int x[maxn];
int sum;

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a%b);
}

int lcm(int a, int b)
{
    return a / gcd(a, b) * b; //防溢出
}

//equ个方程,var个变元 A[r][c], 0= 0; r--)
    {
        temp = A[r][var];
        for(int c = r + 1; c < var; c++)
        {
            if (A[r][c] != 0) temp -= x[c] * A[r][c];
            temp = (temp%mod+mod)%mod;
        }
        while(temp % A[r][r] != 0) temp += mod; //剩余系的特殊处理
        x[r] = (temp / A[r][r])%mod;
        sum += x[r];
    }
    return 0;
}

Matrix A;

int vis[][9] = {1, 1, 0, 1, 0, 0, 0, 0, 0,
                1, 1, 1, 0, 1, 0, 0, 0, 0,
                0, 1, 1, 0, 0, 1, 0, 0, 0,
                1, 0, 0, 1, 1, 0, 1, 0, 0,
                1, 0, 1, 0, 1, 0, 1, 0, 1,
                0, 0, 1, 0, 1, 1, 0, 0, 1,
                0, 0, 0, 1, 0, 0, 1, 1, 0,
                0, 0, 0, 0, 1, 0, 1, 1, 1,
                0, 0, 0, 0, 0, 1, 0, 1, 1
               };
int cot;

int main()
{
    int t, n = 9;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++) A[i][j] = vis[i][j];
        scanf("%d", &t);
        A[i][n] = (mod - t)%mod;
    }

    gauss_elimination(A, n, n);

    for(int i = 0; i < n; i++)
    {
        while(x[i]--)
        {
            printf("%d", i+1);
            sum--;
            printf(sum > 0 ? " " : "\n");
        }
    }

    return 0;
}
 
  
 
  
 
  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define FOP freopen("data.txt","r",stdin)
#define FOP2 freopen("data1.txt","w",stdout)
#define inf 0x3f3f3f3f
#define maxn 310
#define mod 4
#define PI acos(-1.0)
#define LL long long
using namespace std;

typedef int Matrix[maxn][maxn];
int x[maxn];
int sum;

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a%b);
}

int lcm(int a, int b)
{
    return a / gcd(a, b) * b; //防溢出
}

//equ个方程,var个变元 A[r][c], 0 abs(A[max_r][col]) && A[r][col] != 2) max_r = r; //跳过2
        }
        if(max_r != row) for(int c = 0; c <= var; c++) swap(A[max_r][c], A[row][c]);


        //与第row+1~equ行进行消元
        int LCM, ta, tb;
        for(int r = row+1; r < equ; r++)
        {
            if(A[r][col] == 0) continue;

            LCM = lcm(abs(A[r][col]),abs(A[row][col]));
            ta = LCM / abs(A[r][col]);
            tb = LCM / abs(A[row][col]);
            if(A[r][col] * A[row][col] < 0) tb = -tb;//异号的情况是相加
            for(int c = col; c <= var; c++)
            {
                A[r][c] = A[r][c] * ta - A[row][c] * tb;
                A[r][c] = (A[r][c]%mod+mod)%mod;
            }
        }
    }

    int temp;
    for (int r = var - 1; r >= 0; r--)
    {
        temp = A[r][var];
        for(int c = r + 1; c < var; c++)
        {
            if (A[r][c] != 0) temp -= x[c] * A[r][c];
            temp = (temp%mod+mod)%mod;
        }
        while(temp % A[r][r] != 0) temp += mod; //剩余系的特殊处理
        x[r] = (temp / A[r][r])%mod;
        sum += x[r];
    }
    return 0;
}

Matrix A;

int vis[][9] = {1, 1, 0, 1, 0, 0, 0, 0, 0,
                1, 1, 1, 0, 1, 0, 0, 0, 0,
                0, 1, 1, 0, 0, 1, 0, 0, 0,
                1, 0, 0, 1, 1, 0, 1, 0, 0,
                1, 0, 1, 0, 1, 0, 1, 0, 1,
                0, 0, 1, 0, 1, 1, 0, 0, 1,
                0, 0, 0, 1, 0, 0, 1, 1, 0,
                0, 0, 0, 0, 1, 0, 1, 1, 1,
                0, 0, 0, 0, 0, 1, 0, 1, 1
               };
int cot;

int main()
{
    int t, n = 9;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++) A[i][j] = vis[i][j];
        scanf("%d", &t);
        A[i][n] = (mod - t)%mod;
    }

    gauss_elimination(A, n, n);

    for(int i = 0; i < n; i++)
    {
        while(x[i]--)
        {
            printf("%d", i+1);
            sum--;
            printf(sum > 0 ? " " : "\n");
        }
    }

    return 0;
}


你可能感兴趣的:(poj_1166 The Clocks(高斯消元))