HDU 5755 Gambler Bo(高斯消元裸题)——2016 Multi-University Training Contest 3

来源:互联网 发布:护眼仪有用吗 知乎 编辑:程序博客网 时间:2024/05/23 01:12

传送门

Gambler Bo

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 326    Accepted Submission(s): 128
Special Judge


Problem Description
Gambler Bo is very proficient in a matrix game.

You have a N×M matrix, every cell has a value in {0,1,2}.

In this game, you can choose a cell in the matrix, plus 2 to this cell, and plus 1 to all the adjacent cells.

for example, you choose the cell (x,y), the value of (x,y) will be plused 2, and the value of (x1,y)(x+1,y)(x,y1)(x,y+1) will be plused 1.

if you choose the cell (1,2), the cell (1,2) will be plused 2, and the cell (2,2)(1,1)(1,3) will be plused 1, the cell (0,2) won’t be changed because it’s out of the matrix.

If the values of some cells is exceed 2, then these values will be modulo 3.

Gambler Bo gives you such a matrix, your task is making all value of this matrix to 0 by doing above operations no more than 2NM times.
 

Input
First line, an integer T. There are T test cases.

In each test, first line is two integers N,M, and following N lines describe the matrix of this test case.

T10,1N,M30, the matrix is random and guarantee that there is at least one operation solution.
 

Output
For each test, first line contains an integer num(0num2NM) describing the operation times.

Following num lines, each line contains two integers x,y(1xN,1yM) describing the operation cell.

The answer may not be unique, you can output any one.
 

Sample Input
2
2 3
2 1 2
0 2 0
3 3
1 0 1
0 1 0
1 0 1
 

Sample Output
1
1 2
5
1 1
1 3
2 2
3 1
3 3

题目大意:
给定一个M*N的矩阵,这个矩阵中的值只是{1,2,0}中的一个,然后我们需要进行一些操作,选择一个矩阵中的格子,然后这个格子中的数会加上2,当然结果需要对3取模,然后与这个格子相邻的每个格子都得加上1,结果对3取模,求进行多少次操作之后所有的格子中的数都变成0,并输出操作的顺序。

解题思路:
这个题目就是一个高斯消元的裸题,相当于开关问题和翻转问题,就是求一个矩阵能够影响的矩阵,具体操作可以看这个POJ1681题解然后进行模3,然后套上模板就行了,我们没有时间来得及看。

My Code:

#include <iostream>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>using namespace std;vector<int> ans;const int MAXN = 900+5;int equ, var;///equ个方程 var个变量int a[MAXN][MAXN];///增广矩阵int x[MAXN];///解的数目bool 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 a, int b){    return a/GCD(a,b)*b;}int Gauss(){    int Max_r;///当前列绝对值最大的存在的行    ///col:处理当前的列    int row = 0;    int free_x_num;    int free_index = -1;    for(int col=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(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];                    a[i][j] = (a[i][j]%3+3)%3;                }            }        }    }    /**if(row < var)    {        for(int i=row-1; i>=0; i--)        {            free_x_num = 0;            for(int j=0; j<var; j++)                if(a[i][j] && free_x[j])                {                    free_x_num++;                    free_index = j;                }            if(free_x_num>1 || free_index==-1)                continue;            int tmp = a[i][var];            for(int j=0; j<var; j++)                if(a[i][j] && j!=free_index)                {                    tmp -= a[i][j]*x[j];                    tmp = (tmp%3+3)%3;                }            x[free_index] = (tmp*a[i][free_index]);/// 求出该变元.            x[free_index] %= 3;            free_x[free_index] = 0; /// 该变元是确定的.        }        return var - row;///自由变元的个数    }*/    for(int i=var-1; i>=0; i--)    {        int tmp = a[i][var];        for(int j=i+1; j<var; j++)            if (a[i][j])            {                tmp -= a[i][j]*x[j];                tmp = (tmp%3+3)%3;            }        x[i] = tmp*a[i][i];        x[i] %= 3;    }    return 0;///唯一解}int main(){    int T, m, n;    scanf("%d",&T);    while(T--)    {        ans.clear();        scanf("%d%d",&m,&n);        equ = var = m*n;        memset(a, 0, sizeof(a));        for(int i=0; i<var; i++)        {            int ta = i%n, tb = i/n;            a[i][i] = 2;            if(ta > 0)                a[i][i-1] = 1;            if(ta < n-1)                a[i][i+1] = 1;            if(tb > 0)                a[i][i-n] = 1;            if(tb < m-1)                a[i][i+n] = 1;        }        for(int i=0; i<m; i++)        {            for(int j=0; j<n; j++)            {                int tt;                scanf("%d",&tt);                a[i*n+j][var] = ((3-tt)%3);            }        }        int S = Gauss();        for(int i=0; i<var; i++)        {            while(x[i])            {                x[i]--;                ans.push_back(i);            }        }        printf("%d\n",ans.size());        for(int i=0; i<ans.size(); i++)        {            int ta = ans[i]%n;            int tb = ans[i]/n;            printf("%d %d\n", tb+1, ta+1);        }    }    return 0;}

0 0
原创粉丝点击