[笔记][中国大学mooc][程序设计与算法(二) 算法基础][枚举][局部枚举法] POJ1222 熄灯问题

一个人想着一个人 提交于 2020-02-26 14:03:06

题目

在这里插入图片描述

分析

按照一般的穷举法,一共有30个开关,所以解空间有2302^{30}个可能,需要减少枚举数目:

如果存在某个局部,一旦这个局部的状态被确定,那么剩余其他部分的状态只能是确定的一种,或者不多的n种,那么就只需枚举这个局部的状态即可

对于本题目,第一行开关按下的状态可以决定剩余所有的状态,将解空间大小缩小为252^{5}
在这里插入图片描述

代码

#include <stdio.h>
int solve(char puzzle[][6], char result[][6]){
	int cnt1, cnt2;
	for(cnt1 = 1; cnt1 < 5; cnt1++){
		for(cnt2 = 0; cnt2 < 6; cnt2++){
			if(puzzle[cnt1 - 1][cnt2] == 1){
				result[cnt1][cnt2] = 1;
				puzzle[cnt1 - 1][cnt2] = !puzzle[cnt1 - 1][cnt2];
				puzzle[cnt1][cnt2] = !puzzle[cnt1][cnt2];
				if(cnt1+1 < 5) puzzle[cnt1+1][cnt2] = !puzzle[cnt1+1][cnt2];
				if(cnt2-1 >= 0) puzzle[cnt1][cnt2-1] = !puzzle[cnt1][cnt2-1];
				if(cnt2+1 < 6) puzzle[cnt1][cnt2+1] = !puzzle[cnt1][cnt2+1];
			}
			else result[cnt1][cnt2] = 0;
		}
	}
	for(cnt2 = 0; cnt2 < 6; cnt2++) if(puzzle[4][cnt2] != 0) return 0;
	return 1;
}
int main(){
	int puzzleNumber;
	char puzzle[5][6];
	char puzzleTemp[5][6];
	char result[5][6];
	int cnt, cnt1, cnt2, cnt3, tmp;
	scanf("%d", &puzzleNumber);
	for(cnt = 0; cnt < puzzleNumber; cnt++){
		for(cnt1 = 0; cnt1 < 5; cnt1++)
			for(cnt2 = 0; cnt2 < 6; cnt2++)
				scanf("%d", &puzzle[cnt1][cnt2]);
		printf("PUZZLE #%d\n", cnt+1);
		//枚举,从00000到11111
		for(cnt3 = 0; cnt3 < 64; cnt3++){
			tmp = cnt3;
			//将枚举元分解为第一行的操作
			for(cnt2 = 0; cnt2 < 6; cnt2++){
				result[0][cnt2] = tmp % 2;
				tmp /= 2;
			}
			//模拟对象初始化
			for(cnt1 = 0; cnt1 < 5; cnt1++)
				for(cnt2 = 0; cnt2 < 6; cnt2++)
					puzzleTemp[cnt1][cnt2] = puzzle[cnt1][cnt2];
			//执行第一行操作
			for(cnt2 = 0; cnt2 < 6; cnt2++){
				if(result[0][cnt2] == 1){
					puzzleTemp[0][cnt2] = !puzzleTemp[0][cnt2];
					puzzleTemp[1][cnt2] = !puzzleTemp[1][cnt2];
					if(cnt2-1 >= 0) puzzleTemp[0][cnt2-1] = !puzzleTemp[0][cnt2-1];
					if(cnt2+1 < 6) puzzleTemp[0][cnt2+1] = !puzzleTemp[0][cnt2+1];
				}
			}
			//执行接下来几行的操作,观察是否可以熄灭所有灯
			if(solve(puzzleTemp, result))
				for(cnt1 = 0; cnt1 < 5; cnt1++)
					printf("%d %d %d %d %d %d\n", result[cnt1][0], result[cnt1][1], result[cnt1][2], result[cnt1][3], result[cnt1][4], result[cnt1][5]);
		}
	}
	return 0;
} 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!