Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7817 | Accepted: 5087 |
Description
Input
Output
Sample Input
2 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 0 0 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 1 1 0 1 1 0 0 0 1 0 1 0 0
Sample Output
PUZZLE #1 1 0 1 0 0 1 1 1 0 1 0 1 0 0 1 0 1 1 1 0 0 1 0 0 0 1 0 0 0 0 PUZZLE #2 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 1 1 0 1 1 0 1
醉了,学校大二下学期才开线代。花了那么长时间就只为了看概念。。。o(╯□╰)o
明天补上模板。顺便ORZ大bin神。
题意:有一个5*6的矩阵,每个元素代表1盏灯,0表示灯关,1表示灯开。若你改变了第a[i][j]盏灯的状态,相应地还会改变它四周a[i-1][j]、a[i][j-1]、a[i+1][j]、a[i][j+1]这些灯的状态。因为同一盏灯连续按两次又回到初始状态,所以每个灯只需按一次,若选择按第a[i][j]盏灯,则x[i][j] = 1,否则为0。现在给你这些灯的初始状态,让你找出一种方案x[][]使得所有灯全熄灭。
高斯消元——解n元一次线性方程组。
1,将方程组化简成增广矩阵A;
2,利用列主元法 + 加减消元法 进行消元,将矩阵A变成阶梯矩阵;
3,在解唯一的情况下,形成严格的上三角矩阵,然后就是回代过程——自底向上求所有变量的解。
思路:入门题目吧,构建的矩阵比较简单。
对每盏灯,列一个异或方程,把可能影响它的灯和自己置1,其余灯置0。
比如说灯初始状态为a[i][j],全灭的方案为x[i][j]。
则有——
a[i][j] ^ x[i-1][j]*1 ^ x[i][j-1]*1 ^ x[i+1][j]*1 ^ x[i][j+1]*1 ^ x[i][j]*1 ^ (其余不相关的灯*0) = 0。
两边同时异或a[i][j]得
x[i-1][j]*1 ^ x[i][j-1]*1 ^ x[i+1][j]*1 ^ x[i][j+1]*1 ^ x[i][j]*1 ^ (其余不相关的灯*0) = a[i][j]。
30个方程组,30个变元,然后直接模板KO。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int a[31][31];//增广矩阵 int equ, var;//equ个方程 var个变元 int x[31];//解 void init_A() { memset(a, 0, sizeof(a)); equ = 30, var = 30;//30个方程 30个变元 for(int i = 0; i < 5; i++) { for(int j = 0; j < 6; j++) { a[i*6+j][i*6+j] = 1; if(i > 0) a[i*6+j][(i-1)*6+j] = 1; if(j > 0) a[i*6+j][i*6+j-1] = 1; if(i < 4) a[i*6+j][(i+1)*6+j] = 1; if(j < 5) a[i*6+j][i*6+j+1] = 1; } } for(int i = 0; i < 30; i++) scanf("%d", &a[i][30]); } int Gauss() { int k, max_r; int col = 0; for(k = 0; k < equ && col < var; k++, col++) { //列主元法 //找第col元素绝对值最大的行i(i > k) 与 当前行交换 max_r = k; for(int i = k + 1; i < equ; i++) if(a[i][col] > a[k][col]) max_r = i; if(max_r != k)//找到 —— 交换 { for(int i = col; i < var+1; i++) swap(a[k][i], a[max_r][i]); } if(a[k][col] == 0)//k行下面的元素全为0 { k--; continue; } //加减消元 for(int i = k + 1; i < equ; i++) { if(a[i][col] != 0) { for(int j = col; j < var+1; j++) a[i][j] ^= a[k][j]; } } } //根据上三角矩阵 回代求解 for(int i = var-1; i >= 0; i--) { x[i] = a[i][var]; for(int j = i + 1; j < var; j++) x[i] ^= (a[i][j] * x[j]); } return 0; } int main() { int t, k = 1; scanf("%d", &t); while(t--) { init_A(); Gauss(); printf("PUZZLE #%d\n", k++); for(int i = 0; i < 30; i++) { if((i+1) % 6 == 0) printf("%d\n", x[i]); else printf("%d ", x[i]); } } return 0; }