poj1222 EXTENDED LIGHTS OUT (高斯消元)

来源:互联网 发布:淘宝联盟登录不了 编辑:程序博客网 时间:2024/05/29 19:45
EXTENDED LIGHTS OUT
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 9270 Accepted: 6019

Description

In an extended version of the game Lights Out, is a puzzle with 5 rows of 6 buttons each (the actual puzzle has 5 rows of 5 buttons each). Each button has a light. When a button is pressed, that button and each of its (up to four) neighbors above, below, right and left, has the state of its light reversed. (If on, the light is turned off; if off, the light is turned on.) Buttons in the corners change the state of 3 buttons; buttons on an edge change the state of 4 buttons and other buttons change the state of 5. For example, if the buttons marked X on the left below were to be pressed,the display would change to the image on the right. 

The aim of the game is, starting from any initial set of lights on in the display, to press buttons to get the display to a state where all lights are off. When adjacent buttons are pressed, the action of one button can undo the effect of another. For instance, in the display below, pressing buttons marked X in the left display results in the right display.Note that the buttons in row 2 column 3 and row 2 column 5 both change the state of the button in row 2 column 4,so that, in the end, its state is unchanged. 

Note: 
1. It does not matter what order the buttons are pressed. 
2. If a button is pressed a second time, it exactly cancels the effect of the first press, so no button ever need be pressed more than once. 
3. As illustrated in the second diagram, all the lights in the first row may be turned off, by pressing the corresponding buttons in the second row. By repeating this process in each row, all the lights in the first 
four rows may be turned out. Similarly, by pressing buttons in columns 2, 3 ?, all lights in the first 5 columns may be turned off. 
Write a program to solve the puzzle.

Input

The first line of the input is a positive integer n which is the number of puzzles that follow. Each puzzle will be five lines, each of which has six 0 or 1 separated by one or more spaces. A 0 indicates that the light is off, while a 1 indicates that the light is on initially.

Output

For each puzzle, the output consists of a line with the string: "PUZZLE #m", where m is the index of the puzzle in the input file. Following that line, is a puzzle-like display (in the same format as the input) . In this case, 1's indicate buttons that must be pressed to solve the puzzle, while 0 indicate buttons, which are not pressed. There should be exactly one space between each 0 or 1 in the output puzzle-like display.

Sample Input

20 1 1 0 1 01 0 0 1 1 10 0 1 0 0 11 0 0 1 0 10 1 1 1 0 00 0 1 0 1 01 0 1 0 1 10 0 1 0 1 11 0 1 1 0 00 1 0 1 0 0

Sample Output

PUZZLE #11 0 1 0 0 11 1 0 1 0 10 0 1 0 1 11 0 0 1 0 00 1 0 0 0 0PUZZLE #21 0 0 1 1 11 1 0 0 0 00 0 0 1 0 01 1 0 1 0 11 0 1 1 0 1
题目大意:经典的开关灯问题(自行百度)。
解题思路:方法一:用搜索勉强可以卡过去,用二进制压缩枚举第一行的状态......
方法二:高斯消元
0ms就A了。
问题是要怎么构造矩阵呢。大家的思路一样,我就不打了,复制别人的2333.
摘自 http://www.cnblogs.com/devtang/archive/2012/07/24/2606728.html

这题分析如下:未知数共30个,因为30个灯的状态我们都必须要确定下来才能解决这道题。

比如说(1,1)这个灯的最终状态将由(1,1),(1,2),(2,1)这三个灯的状态决定这样就可以列出一个方程:

(l(1,1)+x(1,1)+x(1,2)+0*x(1,3)+...+x(2,1)+...)%2=0(l表示给出的初始状态的矩阵,x表示最终需要求的开关矩阵),再比如说对于(1,2)这个灯的状态又可列出一个方程:

(l(1,2)+x(1,1)+x(1,2)+x(1,3)+...+x(2,2)+...)%2=0这样对于30个位置我们可以列出30个方程(不相关),共有30个未知数,故方程一定有唯一解。

现在就我来说吧,2333,矩阵构造完,把l(x,y)这个常数项移到右边去。

因为是(mod2)的,所以用一下exgcd求一下同余方程就可以了

MOD2跟MOD7原理一样。

加注释的代码如下:

#include<cmath>#include<cstdio>#include<cstring>#include<iostream> #include<algorithm> using namespace std;const int maxn=40,n=30,m=30,MOD=2;int x,y,cas=1;double matrix[maxn][maxn],mp[maxn][maxn];int gcd(int a,int b){return b==0?a:gcd(b,a%b);}bool pd(double x,double y)//判断是否越界{if(x<0||x>=5||y<0||y>=6)return false;return true;}void initmatrix(){for(int i=0;i<5;i++)for(int j=0;j<6;j++)scanf("%lf",&mp[i][j]);for(int i=0;i<30;i++)//30个位置,30个变量 {for(int j=0;j<30;j++)matrix[i][j]=0;//矩阵初始化 int a,b,c,d;//上下左右 int row=i/6,col=i-row*6;matrix[i][i]=1;//当前位置 matrix[i][m]=mp[row][col];a=i-6;if(pd(row-1,col))matrix[i][a]=1;//上 b=i+6;if(pd(row+1,col))matrix[i][b]=1;//下c=i-1;if(pd(row,col-1))matrix[i][c]=1;//左 d=i+1;if(pd(row,col+1))matrix[i][d]=1;//右}}int exgcd(int m,int& x,int n,int& y)//exgcd求同余方程 {int x1=0,y1=1,x0=1,y0=0,r=(m%n+n)%n,q=(m-r)/n;x=0,y=1;while(r)x=x0-q*x1,y=y0-q*y1,x0=x1,y0=y1,x1=x,y1=y,m=n,n=r,r=m%n,q=(m-r)/n;return n;}void presolve(){for(int i=0;i<n;i++)//用第i行对其他行进行逐步消元 {int maxrow=i;for(int j=i+1;j<n;j++)if(fabs(matrix[j][i])>fabs(matrix[maxrow][i]))maxrow=j;if(maxrow!=i)for(int j=0;j<=m;j++)swap(matrix[i][j],matrix[maxrow][j]);if(matrix[i][i]==0)continue;for(int k=i+1;k<n;k++)//对k行进行消元 {double f=matrix[k][i]/matrix[i][i]; for(int j=i;j<=m;j++){matrix[k][j]-=f*matrix[i][j];matrix[k][j]=((int)matrix[k][j]%MOD+MOD)%MOD;} }}}void cal(){for(int i=n-1;i>=0;i--){double ans=0;for(int j=i+1;j<n;j++){ans+=matrix[j][m]*matrix[i][j];matrix[i][m]-=matrix[j][m]*matrix[i][j];matrix[i][m]=((int)matrix[i][m]%MOD+MOD)%MOD;}int M=exgcd((int)matrix[i][i],x,MOD,y);x=x*matrix[i][m]/M;x=(x%(MOD/M)+MOD/M)%(MOD/M);matrix[i][m]=x;}}void output(){int id=0;printf("PUZZLE #%d\n",cas++);for(int i=0;i<5;i++){for(int j=0;j<6;j++)printf("%s%.0lf",j?" ":"",matrix[id++][30]);printf("\n");}}int main(){int T;scanf("%d",&T);while(T--)initmatrix(),presolve(),cal(),output();}


0 0
原创粉丝点击