题意:关灯游戏,给出一个状态,求关灯方案。
题解:由于控制矩阵是确定的,并且是满秩的,所以解唯一。
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 30
int a[MAXN][MAXN], b[MAXN];
int Gauss ( int n, int a[][MAXN], int b[] )
{
int i, j, k, row;
for ( k = 0; k < n; k++ )
{
for ( i = k; i < n; i++ )
if ( a[i][k] == 1 ) { row = i; break; }
if ( i == n ) return 0; //由于控制矩阵可逆,所以x[]是有唯一解的,此处也可省略
if ( row != k )
{
for ( j = k; j < n; j++ )
swap ( a[k][j], a[row][j] );
swap ( b[k], b[row] );
}
for ( i = k + 1; i < n; i++ )
{
if ( a[i][k] == 0 ) continue; //按行处理
for ( j = k + 1; j < n; j++ )
a[i][j] ^= a[k][j];
b[i] ^= b[k];
}
}
b[n-1] = b[n-1] / a[n-1][n-1];
for ( i = n - 2; i >= 0; i-- )
{
for ( j = i + 1; j < n; j++ )
b[i] ^= ( a[i][j] * b[j] );
b[i] = b[i] / a[i][i];
}
return 1;
}
void init ()
{
int i, j;
int t1, t2, t3, t4;
for ( i = 0; i < 30; i++ )
{
t1 = i / 6;
t2 = i % 6;
for ( j = 0; j < 30; j++ )
{
t3 = j / 6;
t4 = j % 6;
if ( abs(t1-t3) + abs(t2-t4) <= 1 )
a[i][j] = 1;
else a[i][j] = 0;
}
}
}
int main()
{
int t, k, i;
scanf("%d",&t);
for ( k = 1; k <= t; k++ )
{
for ( i = 0; i < 30; i++ )
scanf("%d",&b[i]);
init();
Gauss ( 30, a, b );
printf("PUZZLE #%d\n",k);
for ( i = 1; i <= 30; i++ )
{
printf("%d ", b[i-1]);
if ( i % 6 == 0 ) printf("\n");
}
}
return 0;
}
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 30
int a[MAXN][MAXN], b[MAXN];
int Gauss ( int n, int a[][MAXN], int b[] )
{
int i, j, k, row;
for ( k = 0; k < n; k++ )
{
for ( i = k; i < n; i++ )
if ( a[i][k] == 1 ) { row = i; break; }
if ( i == n ) return 0; //由于控制矩阵可逆,所以x[]是有唯一解的,此处也可省略
if ( row != k )
{
for ( j = k; j < n; j++ )
swap ( a[k][j], a[row][j] );
swap ( b[k], b[row] );
}
for ( j = k + 1;j < n; j++ ) //按列处理
for ( i = k + 1; i < n; i++ )
a[i][j] ^= ( a[i][k] * a[k][j] ); // a[i][j] ^= ( a[i][k] / a[k][k] * a[k][j] ); a[k][k] == 1;
for ( i = k + 1; i < n; i++ )
b[i] ^= ( a[i][k] * b[k] );
}
//b[n-1] = b[n-1] / a[n-1][n-1]; a[n-1][n-1] == 1;
for ( i = n - 2; i >= 0; i-- )
{
for ( j = i + 1; j < n; j++ )
b[i] ^= ( a[i][j] * b[j] );
//b[i] = b[i] / a[i][i];
}
return 1;
}
void init ()
{
int i, j;
int t1, t2, t3, t4;
for ( i = 0; i < 30; i++ )
{
t1 = i / 6;
t2 = i % 6;
for ( j = 0; j < 30; j++ )
{
t3 = j / 6;
t4 = j % 6;
if ( abs(t1-t3) + abs(t2-t4) <= 1 )
a[i][j] = 1;
else a[i][j] = 0;
}
}
}
int main()
{
int t, k, i;
scanf("%d",&t);
for ( k = 1; k <= t; k++ )
{
for ( i = 0; i < 30; i++ )
scanf("%d",&b[i]);
init();
Gauss ( 30, a, b );
printf("PUZZLE #%d\n",k);
for ( i = 1; i <= 30; i++ )
{
printf("%d ", b[i-1]);
if ( i % 6 == 0 ) printf("\n");
}
}
return 0;
}
本文介绍了一种解决关灯游戏的算法实现,通过构造特定的控制矩阵并利用高斯消元法找到唯一的开关操作方案。适用于30个灯泡组成的6×5网格布局。
&spm=1001.2101.3001.5002&articleId=7323283&d=1&t=3&u=c6d6ec8a26aa44f0b68ef7160a94499c)
1万+

被折叠的 条评论
为什么被折叠?



