The Pilots Brothers' refrigerator

本文探讨了游戏“ThePilotsBrothers:跟随有条纹的大象”中一个有趣的数学挑战——如何使用最少的操作次数打开一扇带有16个开关的冰箱门。通过深度优先搜索算法,我们找到了解决问题的有效方法,并分享了解题思路和C++代码实现。

描述

游戏“The Pilots Brothers:跟随有条纹的大象”有一个玩家需要打开冰箱的任务。

冰箱门上有16个把手。每个手柄可以处于以下两种状态之一:打开或关闭。只有当所有把手都打开时,冰箱才会打开。手柄表示为矩阵4х4。您可以在任何位置[i,j](1≤i,j≤4)更改句柄的状态。但是,这也会更改第i行中所有句柄和第j列中所有句柄的状态。

任务是确定打开冰箱所需的最小手柄切换次数。

输入

输入包含四行。四行中的每一行包含四个描述适当句柄的初始状态的字符。符号“+”表示手柄处于闭合状态,而符号“ - ”表示“打开”。至少一个手柄最初是关闭的。

产量

输入的第一行包含N - 最小切换次数。其余N行描述切换顺序。每行包含由一个或多个空格分隔的矩阵的行号和列号。如果有多种解决方案,您可以提供其中任何一种解决方案。

Sample Input

-+--
----
----
-+--

Sample Output

6
1 1
1 3
1 4
4 1
4 3
4 4

遍历问题,我用的是dfs,用深搜实现每次记忆化的搜索,设个结果栈,设个过程栈,

更新最少次数的时候更新结果栈的结果。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
int a[4][4];
stack<int> sta;
stack<int> ans;
int Min=0x7fffffff;

int check()//检查
{
    int i,j;
    for(i=0; i<4; ++i)
        for(j=0; j<4; ++j)
            if(a[i][j]!=0)
                return -1;
    return 1;
}

void change(int x,int y){
    for(int i=0;i<4;i++){
        a[x][i]=!a[x][i];
    }
    for(int i=0;i<4;i++){
        if(i!=x)           //千万别翻两遍
            a[i][y]=!a[i][y];
    }
}

void dfs(int d,int step)
{
    int x,y;
    if(d==16){
        if(check()==1)
            if(step<Min){
                Min=step;
                ans=sta;
            }
        return;
    }else{
        x=d/4;
        y=d%4;
        dfs(d+1,step);
        change(x,y);
        sta.push(d);
        dfs(d+1,step+1);
        sta.pop();
        change(x,y);
    }
}


int main()
{
    char t;
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            cin>>t;
            if(t=='+') a[i][j]=1;
            else a[i][j]=0;
        }
    }

    dfs(0,0);
    if(Min==0x7fffffff)
        cout<<"Impossible"<<endl;
    else
        cout<<Min<<endl;
    if(ans.empty()){
        cout<<"empty"<<endl;
    }

    int x,y,z;
    while(!ans.empty())
    {
        z=ans.top();
        ans.pop();
        x=z/4;
        y=z%4;
        cout<<x+1<<" "<<y+1<<endl;
    }


return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值