捣鼓了一整天。。。。终于弄明白了这个怎么来求解。。。。
这个题的对立面就是说给你一个全熄的矩阵。。。经过一系列变化。。。让它跟题中输入的初始矩阵相等就可以了(mod 2 相当与异或所以可以这样来)。。。。没按下一个按钮相当与加上一个
0 1 0
1 1 1
0 1 0
这样的矩阵。。。。当然了边界情况也是需要考虑进去的。。。。自己可以写出相应的要加上的矩阵的吧。。。。。
设x表示是否按下,a表示要加上的矩阵。。。b表示初始的矩阵。。。则这个题可以表示为。。。
x(1,1)*a(1,1)+x(1,2)*a(1,2)+。。。。+x(5,6)*a(5,6)=b;
然后把x。。a。。b。。都化成一维的就可以了。。。。。而且这个题一定有解(题目给出的)所以很多消元的时候的细节可以直接跳过了。。。嗨皮。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int m[32][32], ans[32];
void gauss(){
int i,j,k;
for (k = 1; k <= 30; k++) {
i = k;
while((m[i][k] == 0) && (i <= 30))
i++;
if(i > k) {
for(j = 1; j <= 31; j++)
swap(m[i][j], m[k][j]);
}
for(i = 1; i <= 30; i++) {
if(i != k && m[i][k])
for(j=1; j<= 31; j++)
m[i][j] ^= m[k][j];
}
}
}
int main() {
int n, i, j, k;
scanf("%d", &n);
for (i = 1; i <= n; i++) {
memset(m, 0, sizeof (m));
for (j = 1; j <= 30; j++) {
scanf("%d", &m[j][31]);
ans[j] = 0;
}
for (j = 1; j <= 30; j++) {
m[j][j] = 1;
if (j % 6 != 1) m[j - 1][j] = 1;
if (j % 6 != 0) m[j + 1][j] = 1;
if (j >= 7) m[j - 6][j] = 1;
if (j <= 24) m[j + 6][j] = 1;
}
gauss();
for(j = 1; j <= 30; j++)
if(m[j][31]){
for(k=1; k <= 30 && !m[j][k]; k++);
if(k <= 30)
ans[j] = m[j][31];
}
printf("PUZZLE #%d\n",i);
for(j=1; j<=30; j++){
printf("%d",ans[j]);
if(j%6==0)
printf("\n");
else
printf(" ");
}
}
return 0;
}