POJ 1222 EXTENDED LIGHTS OUT (高斯消元)

时间:2023-12-16 15:36:56

题目链接

题意:5*6矩阵中有30个灯,操作一个灯,周围的上下左右四个灯会发生相应变化 即由灭变亮,由亮变灭,如何操作使灯全灭?

题解:这个问题是很经典的高斯消元问题。同一个按钮最多只能被按一次,因为按两次跟没有按是一样的效果。那么 对于每一个灯,用1表示按,0表示没有按,那么每个灯的状态的取值只能是01。列出30个方程,30个变元,高斯消元解出即可。打表观察我们可以发现5*6的矩阵是一定有解的,主对角线元素都是1所以一定有唯一解。

打表代码:

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;
char s[][];
int g[][],ans[];//注意这里定义的大小是n^2 不是n
int dir[][]= {{,},{,},{,-},{,},{-,}};
int n,m1,m2;
int gauss()
{
int row,col;
for(row=,col=; row<n&&col<n; col++) //注意是小于n
{
int id=row;
for(int i=row+; i<n; i++)
if(g[i][col]) id=i;
if(g[id][col])
{
for(int k=col; k<=n; k++)
swap(g[id][k],g[row][k]);//注意这里是k
for(int j=row+; j<n; j++)
if(g[j][col])
for(int k=col; k<=n; k++) //注意这里每段代码的特点 一点都不能写错
g[j][k]^=g[row][k];
row++;//一定注意这句话放到if里
}
}
for(int i=;i<n;i++)
{
for(int j=;j<n;j++)
printf("%d ",g[i][j]);
printf(" *******\n");
}
// for(int i=row; i<n; i++)
// if(g[i][n]) return -1;
// int ans=0;
// for(int i=n-1; i>=0; i--)
// {
// for(int j=n-1; j>i; j--)
// g[i][n]^=g[i][j]&&g[j][n];
// ans+=g[i][n];
// }
// return ans;
return -;
}
int main()
{ m1=;m2=;
n=m1*m2;
//
memset(g,,sizeof(g));
for(int i=; i<m1; i++)
for(int j=; j<m2; j++)
for(int k=; k<; k++)
{
int a=i+dir[k][];
int b=j+dir[k][];
if(a>=&&b>=&&a<m1&&b<m2)
g[a*m2+b][i*m2+j]=; //注意这里是 *m2, 模拟几个数就能理解了
}
int ans1,ans2;
ans1=gauss();
return ;
}

AC代码:

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;
int n=;
int f[][];
int g[][];
int dir[][]= {{,},{,},{,},{-,},{,-}};
void input()
{
for(int i=; i<; i++)
scanf("%d",&g[i][]);
}
void work()
{
int row,col;
for(row=,col=; row<n&&col<n; col++)
{
int id=row;
for(int i=id; i<n; i++)
if(g[i][col])
id=i;
if(g[id][col])
{
for(int k=col; k<=n; k++)
swap(g[row][k],g[id][k]);
for(int i=row+; i<n; i++)
if(g[i][col])
for(int k=col; k<=n; k++)
g[i][k]^=g[row][k];
row++;
}
}
//构建上三角完毕 下面开始回代过程
for(int i=n-;i>=;i--)
for(int j=n-;j>i;j--)
g[i][]^=g[i][j]&&g[j][];
//这一行可以参考传统的求解过程来理解
}
void print()
{
for(int i=; i<; i++)
{
if((i+)%!=)
printf("%d ",g[i][]);
else
printf("%d\n",g[i][]);
}
}
void debug()
{
for (int i =; i <; i++)
{
for (int j =; j <; j++)
cout <<""<< g[i][j];
cout << endl;
}
cout << endl;
}
int main()
{
for(int i=; i<; i++)
for(int j=; j<; j++)
for(int k=; k<; k++)
{
int a=i+dir[k][];
int b=j+dir[k][];
if(a>=&&b>=&&a<&&b<)
f[i*+j][a*+b]=;
}
int t,cas=;
scanf("%d",&t);
while(t--)
{
printf("PUZZLE #%d\n",cas++);
memcpy(g,f,sizeof(g));
input();
work();
print();
}
return ;
}