HDU 5755 Gambler Bo
Gambler Bo
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 676 Accepted Submission(s): 274
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 (x−1,y)(x+1,y)(x,y−1)(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.
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 (x−1,y)(x+1,y)(x,y−1)(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.
T≤10,1≤N,M≤30, the matrix is random and guarantee that there is at least one operation solution.
In each test, first line is two integers N,M, and following N lines describe the matrix of this test case.
T≤10,1≤N,M≤30, the matrix is random and guarantee that there is at least one operation solution.
Output
For each test, first line contains an integer num(0≤num≤2NM) describing the operation times.
Following num lines, each line contains two integers x,y(1≤x≤N,1≤y≤M) describing the operation cell.
The answer may not be unique, you can output any one.
Following num lines, each line contains two integers x,y(1≤x≤N,1≤y≤M) 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
用高斯消元法可解。每个位置的结果可以由他本身和四个方向上的变化决定。
那么设横坐标为每个位置上的数值(一共n*m个位置),纵坐标为对这个数值的影响。A[i][j]=1表示j使i+1 ,A[i][j]=2表示j使i+2 同理A[i][j]=0表示j使i+0
那么就可以构造一个(n*m) *(n*m)的方阵。设X为(n*m)*1的矩阵表示n*m个位置每个位置增加的次数, B为(n*m)*1的矩阵,B与题目中给的值有关,这里表示增加多少使得终态为0.
AX=B,解出X矩阵就行了..
卧槽 好烦 写的这么乱,不过还是挺好理解的....
/* *********************************************** Author :guanjun Created Time :2016/7/28 8:36:24 File Name :hdu5755.cpp ************************************************ */ #include <iostream> #include <cstring> #include <cstdlib> #include <stdio.h> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <iomanip> #include <list> #include <deque> #include <stack> #define ull unsigned long long #define ll long long #define mod 3 #define INF 0x3f3f3f3f #define maxn 10010 #define cle(a) memset(a,0,sizeof(a)) const ull inf = 1LL << 61; const double eps=1e-5; using namespace std; int a[1100][1100]; int A[1100][1100]; int x[1100]; int dir[4][2]={1,0,0,1,0,-1,-1,0}; int exgcd(int a,int b,int &x,int &y){ if(!b){x = 1; y = 0; return a;} else{ int r = exgcd(b,a%b,y,x); y -= x * (a/b); return r; } } int lcm(int a,int b){ int x = 0, y =0; return a / exgcd(a,b,x,y) * b; } void Gauss(int n,int m){ int r,c; //列主元消去 for(r=0,c=0;r<n&&c<m;c++){ int maxr=r; for(int i=r+1;i<n;i++)if(abs(A[i][c])>abs(A[maxr][c]))maxr=i; if(maxr!=r)for(int i=c;i<=m;i++)swap(A[r][i],A[maxr][i]); if(!A[r][c])continue; for(int i=r+1;i<n;i++)if(A[i][c]){ int d=lcm(A[i][c],A[r][c]); int t1=d/A[i][c],t2=d/A[r][c]; for(int j=c;j<=m;j++) A[i][j]=((A[i][j]*t1-A[r][j]*t2)%mod+mod)%mod; } r++; } for(int i=r;i<n;i++)if(A[i][m])return ; //从下到上 for(int i=r-1;i>=0;i--){ x[i]=A[i][m]; for(int j=i+1;j<m;j++) x[i]=((x[i]-A[i][j]*x[j])%mod+mod)%mod; int x1=0,y1=0; //这里是用exgcd求逆元,也可以用费马小定理求,如果mod是素数 int d = exgcd(A[i][i],mod,x1,y1); //cout<<"d "<<d<<endl; x1=((x1%mod)+mod)%mod; x[i]=x[i]*x1%mod; } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif //freopen("out.txt","w",stdout); int t,n,m; cin>>t; while(t--){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ for(int j=0;j<m;j++)scanf("%d",&a[i][j]); } cle(A); for(int i=0;i<n*m;i++){ A[i][i]=2;//选择自己 加2 int r=i/m;int c=i%m; for(int j=0;j<4;j++){ int x=r+dir[j][0]; int y=c+dir[j][1]; if(x<n&&x>=0&&y<m&&y>=0)A[i][x*m+y]=1;//四个方向+1 } A[i][n*m]=(3-a[r][c])%3;//每个位置需要加的数 和初始状态有关 } Gauss(n*m,n*m); int cnt=0; vector<int>v; for(int i=0;i<n*m;i++){ while(x[i]){ x[i]--; v.push_back(i); } } printf("%d\n",v.size()); for(int i=0;i<v.size();i++){ int r=v[i]/m; int c=v[i]%m; r++,c++; printf("%d %d\n",r,c); } } return 0; }
原文地址:http://www.cnblogs.com/pk28/
与有肝胆人共事,从无字句处读书。
欢迎关注公众号:
欢迎关注公众号: