POJ - 1222 EXTENDED LIGHTS OUT (高斯消元解異或方程組)

題目鏈接:http://poj.org/problem?id=1222

題目大意:現在有一個5行6列的矩陣,矩陣的每個格子都有一個燈泡,格子的值如果是1代表這個格子的燈泡是亮着的,如果是0就代表這個格子的燈泡是滅的。現在可以對矩陣的任意一個格子做如下操作,如果按下這個格子的按鈕,那麼這個格子及這個格子上面,下面,左邊,右邊的燈泡都會發生變化,如果燈泡一開始是亮着的,那麼它就會熄滅,如果它是滅的,那麼它就會亮起來。現在問你能否進行一系列操作令矩陣內所有的燈泡都熄滅。如果可以就輸出操作的方案,如果不行就輸出“-1”。

題目思路:這個題算是高斯消元的入門題了。我們先考慮如果對同一個格子進行一次操作的話,就會使其周圍的格子發生變化,但再一次操作的話,這個效果又會消失了,所以對於每個格子我們都只需要進行一次操作即可。現在要使整個矩陣的燈泡都熄滅,對於每一個格子,它會被包括自己在內的五個格子所影響(上、下、左、右、自己),因爲前面說了,多次操作後效果又會變回去,所以這些操作我們可以看成爲異或操作,奇數次操作就會產生影響,偶數次就不會產生影響。接着就可以把每一格的影響作爲矩陣的一行,既然最後要變化成全爲0的矩陣,那麼就是要找到一個可以異或成原矩陣的方案。這樣就能借助高斯消元來解決。

具體實現看代碼:

#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef pair<int, int>pii;
const int inf = 0x3f3f3f3f;
const int MX = 30 + 5;
const int mod = 1e9 + 7;


int A[MX][MX], ans[MX], _;

void gauss(int equ, int var) {
	int max_r, col, k;
	for (k = 0, col = 0; k < equ && col < var; k++, col++) {
		max_r = k;
		for (int i = k + 1; i < equ; i++) {
			if (A[i][col] > A[max_r][col]) {
				max_r = i;
			}
		}
		if (A[max_r][col] == 0) {
			k--;
			continue;
		}
		if (max_r != k) {
			for (int j = col; j < var + 1; j++) {
				swap(A[k][j], A[max_r][j]);
			}
		}
		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--) {
		ans[i] = A[i][var];
		for (int j = i + 1; j < var; j++) {
			ans[i] ^= (A[i][j] && ans[j]);
		}
	}
}

int main() {
	//FIN;
	int cas = 1;
	for (scanf("%d", &_); _; _--) {
		clr(ans); clr(A);
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 6; j++) {
				int id = i * 6 + j;
				A[id][id] = 1;
				if (i > 0) A[id - 6][id] = 1;
				if (i < 4) A[id + 6][id] = 1;
				if (j > 0) A[id - 1][id] = 1;
				if (j < 5) A[id + 1][id] = 1;
			}
		}
		for (int i = 0; i < 30; i++) scanf("%d", &A[i][30]);
		gauss(30, 30);
		printf("PUZZLE #%d\n", cas++);
		for (int i = 0; i < 30; i++)
			printf("%d%c", ans[i], i % 6 == 5 ? '\n' : ' ');
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章