程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> UVA 1560 - Extended Lights Out(高斯消元)

UVA 1560 - Extended Lights Out(高斯消元)

編輯:C++入門知識

UVA 1560 - Extended Lights Out(高斯消元)


UVA 1560 - Extended Lights Out

題目鏈接

題意:給定一個矩陣,1代表開著燈,0代表關燈,沒按一個開關,周圍4個位置都會變化,問一個按的方法使得所有燈都變暗

思路:兩種做法:
1、枚舉遞推
這個比較簡單,就枚舉第一行,然後遞推過去,每次如果上一行是亮燈,則下一行開關必須按下去

2、高斯消元,
這個做法比較屌一些,每個位置對應上下左右中5個位置可以列出一個異或表達式,然後30個位置對應30個異或表達式,利用高斯消元法就能求出每個位置的解了

代碼:

高斯消元法:

#include 
#include 
#include 
using namespace std;

const int d[5][2] = {{0, 0}, {0, 1}, {0, -1}, {1, 0}, {-1, 0}};

int t, a[31][31], out[6][6];

void back() {
    for (int i = 29; i >= 0; i--)
	out[i / 6][i % 6] = a[i][30];
}

void guess() {
    for (int i = 0; i < 30; i++) {
	int k = i;
	for (; k < 30; k++)
	    if (a[k][i]) break;
	for (int j = 0; j <= 30; j++)
	    swap(a[i][j], a[k][j]);
	for (int j = 0; j < 30; j++) {
	    if (i == j) continue;
	    if (a[j][i]) {
		for (int k = i; k <= 30; k++)
		    a[j][k] ^= a[i][k];
	    }
	}
    }
    back();
}

int main() {
    int cas = 0;
    scanf("%d", &t);
    while (t--) {
	memset(a, 0, sizeof(a));
	for (int i = 0; i < 30; i++)
	    scanf("%d", &a[i][30]);
	for (int i = 0; i < 30; i++) {
	    int x = i / 6, y = i % 6;
	    for (int j = 0; j < 5; j++) {
		int xx = x + d[j][0];
		int yy = y + d[j][1];
		if (xx < 0 || xx >= 5 || yy < 0 || yy >= 6) continue;
		a[i][xx * 6 + yy] = 1;
	    }
	}
	guess();
	printf("PUZZLE #%d\n", ++cas);
	for (int i = 0; i < 5; i++) {
	    for (int j = 0; j < 5; j++)
		printf("%d ", out[i][j]);
	    printf("%d\n", out[i][5]);
	}
    }
    return 0;
}


枚舉遞推:

#include 
#include 
#include 
using namespace std;

const int d[5][2] = {{0, 0}, {1, 0}, {-1, 0}, {0, 1}, {0, -1}};
const int N = 6;
int t, g[N][N], tmp[N][N], out[N][N];

bool judge(int s) {
    memset(out, 0, sizeof(out));
    for (int i = 0; i < 5; i++)
	for (int j = 0; j < 6; j++)
	    tmp[i][j] = g[i][j];
    for (int i = 0; i < 6; i++) {
	if (s&(1<= 5 || yy >= 6) continue;
		tmp[xx][yy] = (!tmp[xx][yy]);
	    }
	}
    }
    for (int i = 1; i < 5; i++) {
	for (int j = 0; j < 6; j++) {
	    if (tmp[i - 1][j]) {
		out[i][j] = 1;
		for (int k = 0; k < 5; k++) {
		    int xx = i + d[k][0];
		    int yy = j + d[k][1];
		    if (xx < 0 || yy < 0 || xx >= 5 || yy >= 6) continue;
		    tmp[xx][yy] = (!tmp[xx][yy]);
		}
	    }
	}
    }
    for (int i = 0; i < 6; i++)
	if (tmp[4][i]) return false;
    return true;
}

void solve() {
    for (int i = 0; i < (1<<6); i++)
	if (judge(i)) return;
}

int main() {
    int cas = 0;
    scanf("%d", &t);
    while (t--) {
	for (int i = 0; i < 5; i++)
	    for (int j = 0; j < 6; j++)
		scanf("%d", &g[i][j]);
	solve();
	printf("PUZZLE #%d\n", ++cas);
	for (int i = 0; i < 5; i++) {
	    for (int j = 0; j < 5; j++)
		printf("%d ", out[i][j]);
	    printf("%d\n", out[i][5]);
	}
    }
    return 0;
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved