# 费解的开关(二进制+递推+思维)
Posted sstealer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# 费解的开关(二进制+递推+思维)相关的知识,希望对你有一定的参考价值。
费解的开关(二进制+递推+思维)
- 题意:5*5的灯阵,每次按一盏灯的开关,并且这盏灯的上下左右也受到相同的影响(0->1,1->0),求使给定灯阵全1的最少步数。
- 题解:
- 每盏灯最多点击一次,点击两次相当于没有点击。
- 最重要的性质:如果我们确定了第1行的灯的情况的话,那么后面的行数都可以依此递推,当前行灭的灯只能由下一行同一列的灯使之点亮。
- 附上一个写的较好的题解
举个例子
11011
10110
01111
11111
第一行中第三盏灯为0,那么必须通过第二行的第3张灯将其点亮,当前行的灯只能由下一行的灯点亮,这样才不会影响当前行其他灯的情况。所以只需要确定第一行的灯的情况即可,第一行的灯控制第二行灯的点击情况,通过第二行灯将第一行灭的灯点亮后, 第二行灯处于灭状态的灯由第三行点亮,依次类推
- Code:
//模块化编程思想
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset((a),0,sizeof(a))
#define fo(i,a,b) for(int (i)=(a);(i)<(b);(i)++)
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)//宏定义,编译时展开,占用编译时间
#define sf(x) scanf("%d",&(x))
const int inf=(0x7f7f7f7f);
const int maxn=3000;
int n;
int mp[5][5];
int dx[]=0,-1,0,1,0;
int dy[]=0,0,1,0,-1;
void turn(int x,int y)
fo(i,0,5)
int xx=x+dx[i];
int yy=y+dy[i];
if(xx>=0&&xx<5&&yy>=0&&yy<5)
mp[xx][yy]^=1;
char mmp[5][5];
int work()
int ans=(1<<30);
int cnt=0;
//fo(i)循环枚举第一行灯的所有可能的点击情况,10010(表示点击第一盏灯和第四盏灯)
fo(i,0,31)
//初始化,
fo(x,0,5)fo(y,0,5)mp[x][y]=mmp[x][y]-'0';
cnt=0;
//通过二进制数解码出灯的点击情况
fo(j,0,5)
if((i>>j)&1)
cnt++;
turn(0,j);
//依次处理前4行灯
fo(j,0,4)
fo(k,0,5)
if(mp[j][k]==0)
turn(j+1,k);//通过下一行的灯使其点亮
cnt++;
//检查第五行灯是否是全亮的情况,如果不是由于前4行是全1的情况
//第五行灭的灯无法点亮,故当前方案不合理
bool is_ok=1;
fo(j,0,5)if(mp[4][j]==0)
is_ok=0;
break;
if(is_ok)
ans=min(ans,cnt);
if(ans>6)return -1;
return ans;
int main()
sf(n);
while(n--)
fo(i,0,5)scanf("%s",mmp[i]);
//fo(i,0,5)fo(j,0,5)cout<<mmp[i][j];
cout<<work()<<endl;
return 0;
以上是关于# 费解的开关(二进制+递推+思维)的主要内容,如果未能解决你的问题,请参考以下文章
JOYOI1266 费解的开关 - 枚举+递推枚举二进制状态