洛谷 P2040 打开所有的灯 题解

这个题写其他题解的dalao们已经解释了

一个灯最多开一次(如果实在不知道为什么看评论区)

这个题一共就9个灯嘛,对吧

递归好想不好写(对于我这种蒟蒻)

所以我写了一个所有题解中最暴力的

直接枚举9个灯的开关状态就可以了

我们把原先的数组开半天在初始化不如弄一个已经全开了的数组开半天看看能不能返回原先的状态就好了更方便一点

//打开所有的灯 九层循环法
#include<bits/stdc++.h>

using namespace std;

inline int read() {//快读
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
	return s*w;
}
inline void write(int x) //快写{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}

int b[11][11],c[11][11],a[11][11],tot,zx = 999;
int xx[] = {0,1,-1,0,0},yy[] = {0,0,0,1,-1},d[10];

int pd(int x) {//判断在哪一行
	if(x <= 3)
		return 1;
	if(x >= 7)
		return 3;
	return 2;
}

void kd(int x,int y) {//开它周围的灯
	for(int i = 0; i <= 4; ++i) {
		int x2 = x + xx[i] , y2 = y + yy[i];
		c[x2][y2] == 1 ? c[x2][y2] = 0 : c[x2][y2] = 1;
	}
}

bool jc() {//判断是否全打开了
	for(int i = 1; i <= 3; ++i)
		for(int j = 1; j <= 3; ++j)
			if(a[i][j] != c[i][j])
				return 0;
	return 1;
}

int main(int argc, char const *argv[]) {
	for(int i = 1; i <= 3; ++i)//读入并初始化c
		for(int j = 1; j <= 3; ++j) {
			a[i][j] = read();
			c[i][j] = 1;
		}
	int he = 0;
	for(d[1] = 0; d[1] <= 1; ++d[1])
		for(d[2] = 0; d[2] <= 1; ++d[2])
			for(d[3] = 0; d[3] <= 1; ++d[3])
				for(d[4] = 0; d[4] <= 1; ++d[4])
					for(d[5] = 0; d[5] <= 1; ++d[5])
						for(d[6] = 0; d[6] <= 1; ++d[6])
							for(d[6] = 0; d[6] <= 1; ++d[6])
								for(d[7] = 0; d[7] <= 1; ++d[7])
									for(d[8] = 0; d[8] <= 1; ++d[8])
										for(d[9] = 0; d[9] <= 1; ++d[9]) {
											for(int i = 1; i <= 9; ++i) {
												if(d[i] == 1) {//如果开着
													kd(pd(i),i % 3 == 0 ? 3 : i % 3);开灯
													he ++;//计数器
													if(he > zx)//如果不是正解直接退出
														break;
												}
											}
											if(jc() && he < zx) {//如果全都开了并且比最小值小
												zx = he;
											}
											he = 0;
											for(int i = 1; i <= 3; ++i)//清空数组
												for(int j = 1; j <= 3; ++j)
													c[i][j] = 1;
										}
	write(zx);
	cout<<endl;
	return 0;
}

友情赠送(递归版本)

//打开所有的灯 递归法
#include<bits/stdc++.h>

using namespace std;

inline int read() {
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
	return s*w;
}
inline void write(int x) {
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}

int b[11][11],c[11][11],a[11][11],tot,zx = 999;
int xx[] = {0,1,-1,0,0},yy[] = {0,0,0,1,-1},d[10];

void kd(int x,int y) {
	for(int i = 0; i <= 4; ++i) {
		int x2 = x + xx[i] , y2 = y + yy[i];
		c[x2][y2] == 1 ? c[x2][y2] = 0 : c[x2][y2] = 1;
	}
}

bool jc() {
	for(int i = 1; i <= 3; ++i)
		for(int j = 1; j <= 3; ++j)
			if(a[i][j] != c[i][j])
				return 0;
	return 1;
}

void dg(int x,int y,int tot) {
	if(x == 4) {
		if(jc() == 1)
			zx = min(zx,tot);
		return ;
	}
	kd(x,y);
	y == 3 ? dg(x + 1,1,tot + 1) : dg(x,y + 1,tot + 1);
	kd(x,y);
	y == 3 ? dg(x + 1,1,tot) : dg(x,y + 1,tot);
}

int main(int argc, char const *argv[]) {
	for(int i = 1; i <= 3; ++i)
		for(int j = 1; j <= 3; ++j) {
			a[i][j] = read();
			c[i][j] = 1;
		}
	int he = 0;
    dg(1,1,0);
    write(zx);
	cout<<endl;
	return 0;
}
posted @ 2019-06-28 09:15  liuzitong本体  阅读(235)  评论(2编辑  收藏  举报