关灯谜题 题解

这是一个使用广度优先搜索(BFS)解决的开关问题。代码中使用了一个队列来进行搜索,并使用一个数组 vis 来记录状态是否已经访问过,避免重复搜索。

首先,定义一个函数 ch,用于根据开关操作更新灯的状态。函数接受两个参数 sopt,其中 s 表示当前的灯状态,opt 表示要执行的开关操作。在函数中,根据开关操作的类型,更新灯的状态。

然后,使用广度优先搜索遍历所有可能的状态。初始状态为所有灯都是开着的,即 sta 的二进制表示全为 1。将初始状态入队,并标记为已访问。接下来,不断从队列中取出状态,并根据每个开关操作更新状态。如果更新后的状态为全关状态(所有位都为 0),则输出当前的深度(操作次数),表示找到了最少操作次数。如果更新后的状态未被访问过,则将其标记为已访问,并将其入队。

最后,如果遍历结束后仍未找到最少操作次数,则输出 -1。

void bfs(){
queue<pair<int,int>>q;
int sta=0;
sta|=(1 << n);
sta--;
vis[sta]=1;
q.push(make_pair(sta,0));
while(!q.empty()) {
int now=q.front().first;
int dep=q.front().second;
q.pop();
if(now==0){
printf("%d\n",dep); return;
}
for(int i=1;i<=m;i++) {
int nxt=ch(now,i);
if(vis[nxt]==1) continue;
vis[nxt]=1;
q.push(make_pair(nxt,dep+1));
}
}
cout<<-1<<endl;
}
1 个赞