poj 1222 EXTENDED LIGHTS OUT
2012-03-17 09:41
309 查看
/* 题意:对于一个5*6的格子,每个格子表示一个灯,每次按下一个按钮,这个按钮和它的上下左右相邻按钮将同时切换各自的亮灭状态, 给定初始状态,问怎么按才能使所有的灯全灭,0表示灯灭,1表示灯亮 注意到每个灯至多只按一次,而按的顺序不影响结果,题目保证有解, 把[i][j]投影到[i*6+j],数组a,x的下标从0开始,线性方程组如下: a(0,0) * x0 + a(0,1) * x1 +...+ a(0,29) * x29 = b0 = a(0,30) a(1,0) * x0 + a(1,1) * x1 +...+ a(1,29) * x29 = b1 = a(1,30) a(2,0) * x0 + a(2,1) * x1 +...+ a(2,29) * x29 = b2 = a(2,30) . . . a(29,0) * x0 + a(29,1) * x1 +...+ a(29,29) * x29 = b29 = a(29,30) 其中 a[i][j]=1 当且仅当按下第 j 个灯会切换第 i 个灯的状态, 令a[i*6+j][30]=b[i*6+j],即a的最后一列表示常数项,a是增广矩阵 */ #include <iostream> //高斯消元 #include <cstring> using namespace std; #define MAXN 31 int equ = 30, var = 30; //equ指方程个数,var指未知数的个数,即矩阵的行和列 int a[MAXN][MAXN], x[MAXN]; //a表示增广矩阵和x表示方程组的解,而a的最后一列表示常数项 int gcd(int a,int b) { if (a==0||b==0) return max(a,b); int i=0,j=0; while (a&1==0) { ++i; a=a>>1; } while (b&1==0) { ++j; b=b>>1; } i=min(i,j); while(1) { if(a<b) swap(a,b); a-=b; if(a==0) return b<<i; while(a&1==0) { a=a>>1; } } } int lcm(int a,int b) { return a/gcd(a,b)*b; } void init() //初始化增广矩阵和方程组的解 { memset(a,0,sizeof(a)); memset(x,0,sizeof(x)); for(int i = 0;i < 5; ++i) for(int j = 0;j < 6; ++j) scanf("%d",&a[i*6+j][30]); // 由于是0,1矩阵,而目标状态是全0,所以可以把初始状态当作目标状态(常数项) int move[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; for(int i = 0;i < 5; ++i) // 系数矩阵a[i][j]为1当且仅当按下第j个灯会切换第i个灯的状态 { for(int j = 0;j < 6; ++j) { a[i*6+j][i*6+j] = 1 ; for(int k = 0;k < 4; ++k) { int tx = i + move[k][0]; int ty = j + move[k][1]; if(!(tx >= 0 && tx < 5 && ty >= 0 && ty < 6)) continue; a[tx*6+ty][i*6+j] = 1 ; //按下灯[i][j]会影响到灯[tx][ty] } } } } void gauss() //题目保证有解 { int col = 0; //当前处理的列 for(int k = 0;k < equ && col < var;++k,++col) { int max_r = k; for(int i = k+1;i < equ; ++i) if(a[i][col] > a[max_r][col]) max_r = i; if(max_r != k) { for(int i = k;i < var + 1; ++i) swap(a[k][i],a[max_r][i]); } if(a[k][col] == 0) { k--; continue; } for(int i = k+1;i < equ; ++i) { if(a[i][col] != 0) { int LCM = lcm(a[i][col],a[k][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)%2 - (a[k][j]*tb)%2 + 2 ) % 2; //a[i][j]只有0和1两种状态 } } } for(int i = var-1;i >= 0; --i) { int tmp = a[i][var] % 2; for(int j = i+1;j < var; ++j) if(a[i][j] != 0) tmp = ( tmp - (a[i][j]*x[j])%2 + 2 ) % 2; x[i] = (tmp/a[i][i]) % 2; } } int main() { int cases; scanf("%d",&cases); for(int k=1;k<=cases;++k) { init(); gauss(); printf("PUZZLE #%d\n",k); for(int i = 0;i < 5; ++i) { for(int j = 0;j < 6; ++j) printf("%d ",x[i*6+j]); printf("\n"); } } return 0; }
相关文章推荐
- poj1222(枚举)熄灯游戏 EXTENDED LIGHTS OUT
- 【POJ】1222 - EXTENDED LIGHTS OUT 反转
- POJ 1222 EXTENDED LIGHTS OUT 高斯消元
- poj1222 EXTENDED LIGHTS OUT(gauss)
- poj 1222 EXTENDED LIGHTS OUT (高斯消元)
- POJ 1222 EXTENDED LIGHTS OUT 高斯消元
- poj 1222 EXTENDED LIGHTS OUT(高斯消元)
- [POJ1222]EXTENDED LIGHTS OUT(高斯消元,异或方程组)
- POJ-1222 EXTENDED LIGHTS OUT(高斯消元)
- poj1222 EXTENDED LIGHTS OUT 高斯消元
- poj 1222 EXTENDED LIGHTS OUT (高斯消元 )
- POJ 1222 EXTENDED LIGHTS OUT
- poj 1222 EXTENDED LIGHTS OUT 增广矩阵消元法
- poj 1222 EXTENDED LIGHTS OUT
- poj 1222 EXTENDED LIGHTS OUT(高斯消元)
- POJ 1222 EXTENDED LIGHTS OUT 高斯消元解异或方程组
- POJ 1222 EXTENDED LIGHTS OUT(熄灯问题——枚举)
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元)
- poj 1222 EXTENDED LIGHTS OUT (高斯消元)
- POJ 1222 EXTENDED LIGHTS OUT