飞行员兄弟

题目描述:

“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。

已知每个把手可以处于以下两种状态之一:打开或关闭。

只有当所有把手都打开时,冰箱才会打开。

把手可以表示为一个4х4的矩阵,您可以改变任何一个位置[i,j]上把手的状态。

但是,这也会使得第i行和第j列上的所有把手的状态也随着改变。

请你求出打开冰箱所需的切换把手的次数最小值是多少。

输入格式

输入一共包含四行,每行包含四个把手的初始状态。

符号“+”表示把手处于闭合状态,而符号“-”表示把手处于打开状态。

至少一个手柄的初始状态是关闭的。

输出格式

第一行输出一个整数N,表示所需的最小切换把手次数。

接下来N行描述切换顺序,每行输入两个整数,代表被切换状态的把手的行号和列号,数字之间用空格隔开。

数据范围

1≤i,j≤4

输入样例:

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

输出样例:

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

注意:如果存在多种打开冰箱的方式,则按照优先级整体从上到下,同行从左到右打开。

看到这道题以为和费解的开关类似,用那个方法做了一遍不对,这道题因为只有16个门把手,所以枚举16中情况就行,用一个二进制为16位的数来表示每个开关的情况,复杂度为O(n^16),

具体解释标注在代码里了

AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<stack>
#include<vector>
#include<queue>
const int INF = 0x3f3f3f3f;
using namespace std;
int a[21][21],i,j,k;
queue<pair<int,int> > ans1;
queue<pair<int,int> > kong; //空序列,用于清空序列
int main()
{
    char ch;
    for (i=1; i<=4; i++)
    {
        for (j=1; j<=4; j++)
        {
            ch=getchar();
            if (ch=='-')
                a[i][j]=1;
        }
        getchar();
    }
    int ans=1e7;
    for (i=1; i<(1<<17); i++)
    {
        int b[21][21];
        memcpy(b,a,sizeof a );
        ans1=kong;
        for (j=1; j<=16; j++)
            if (i>>(j-1) & 1)//取出i的每一位
            {
                int dx=j%4,dy=j/4+1;//当前的行列位置
                if (j%4==0)
                    dx=4,dy--;
                for (k=1;k<=4;k++)
                    b[dy][k]^=1;
                for (k=1;k<=4;k++)
                    if (k!=dy)//特判避免当前点重复操作
                        b[k][dx]^=1;//每一行每一列进行相反操作,
                ans1.push(make_pair(dy,dx));//ans1来储存操作的位置
            }
        bool ok=true;
        for (j=1;j<=4;j++)
            for (k=1;k<=4;k++)
                if (!b[j][k])
                    ok=false;
        if (ok)
            break;
    }
    cout<<ans1.size()<<endl;
    while(!ans1.empty())
    {
        cout<<(ans1.front()).first<<" "<<ans1.front().second<<endl;
        ans1.pop();
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值