标题党,高斯消元法大概就是线代课学的各种初等行变换,我暂且蒙在鼓里,,,
思路:
找出每个灯和开关之间的关系,列出方程组求解。——HINT
以每个开关的状态为未知数列出三十元一次方程组。在其增广矩阵中,矩阵的行与灯一一对应,列与开关一一对应,对于每个开关Y,若Y可控制第X个灯,则X行Y列元素为1,否则为0;每行最后一列(0或1)表示对应灯的初始状态。
例:
对灯阵的初始状态:
0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0
可列出增广矩阵:
1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0
然后对该方程组对应的增广矩阵进行异或行变换。
异或行变换:
与解一般的线性方程组一样,目的是将矩阵化为简化阶梯形,而本题中需要对每行进行异或操作。即当简化至第x行时,
①对换变换:若第x行第x列元素为0,则向下寻找第x列元素为1的行与原第x行进行对换。
②异或变换:至第x行x列元素为1时,从第1行开始,若非x行的第x列元素为1,则该行每个元素对第x行对应元素取异或,否则不操作。如此可保证矩阵中除最后一列外只有第x行第x列的元素为1,即形成简化阶梯形。
步骤:
1.输入5x6的矩阵(input);
2.将其转化为30x31的增广矩阵(equation);
3.行变换(rowoperate);
4.以矩阵形式输出30x31矩阵的最后一列(output);
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int n = 30;
const int k = 5;
void input(int [][k + 1]);
void equation(int [][k + 1], int [][n + 1]);
void rowoperate(int , int [][n + 1]);
void ans(int [][n + 1]);
int main(){
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int m;
int arr[k][k + 1], arr2[n][n + 1];
scanf("%d", &m);
for (int t = 1; t <= m; t++)
{
input(arr);
memset(arr2, 0, sizeof(int) * n * (n + 1));
equation(arr, arr2);
printf("PUZZLE #%d\n", t);
for (int i = 0; i < n; i++)
rowoperate(i, arr2);
ans(arr2);
}
return 0;
}
void input(int arr[][k + 1])
{
for (int x = 0; x < k; x++)
for (int y = 0; y <= k; y++)
scanf("%d", &arr[x][y]);
}
void equation(int arr[][k + 1], int arr2[][n + 1])
{
for (int x = 0; x < k; x++)
for (int y = 0; y <= k; y++)
{
int pos = x * (k + 1) + y;
arr2[pos][n] = arr[x][y];
arr2[pos][pos] = 1;
if (x > 0)
arr2[pos][pos - (k + 1)] = 1;
if (x < k - 1)
arr2[pos][pos + (k + 1)] = 1;
if (y > 0)
arr2[pos][pos - 1] = 1;
if (y < k)
arr2[pos][pos + 1] = 1;
}
}
void rowoperate(int i, int arr2[][n + 1])
{
if (arr2[i][i] == 0)
{
int j = i + 1, temp;
while (arr2[j][i] == 0)
j++;
for (int y = 0; y <= n; y++)
{
temp = arr2[j][y];
arr2[j][y] = arr2[i][y];
arr2[i][y] = temp;
}
}
for (int x = 0; x < n; x++)
{
if (x == i)
continue;
if (arr2[x][i] == 1)
for (int y = 0; y <= n; y++)
{
arr2[x][y] ^= arr2[i][y];
}
}
}
void ans(int arr2[][n + 1])
{
for (int x = 0; x < n; x++)
{
printf("%d", arr2[x][n]);
x % 6 == 5 ? puts("") : putchar(' ');
}
}