Acwing_116.飞行员兄弟

作者:指针不指南吗
专栏:算法刷题

🐾或许会很慢,但是不可以停下🐾

题目

116.飞行员兄弟
在这里插入图片描述

收获

  1. vector+pair的用法
  2. 先算时间复杂度,是否枚举,没法子也枚举吧
  3. 位运算tql了

补充知识

(1)左移运算符 (<<):
用途: 将整数的二进制表示向左移动指定位数,用0填充空位。
示例: 1 << 16 将1左移16位,生成一个代表65536的二进制数,用于表示16个灯泡的所有可能状态。
(2)右移运算符 (>>):
用途: 将整数的二进制表示向右移动指定位数,左侧空位填充取决于符号位。
示例: op >> get(i,j) > 根据位置(i,j)右移op,用于检查特定灯泡的开关状态。
(3)与运算符 (&):
用途: 对两个数的二进制表示进行位与操作,只有当两位都为1时结果位才为1。
示例: op >> get(i,j) & 1 > 用于确定经过右移操作后的数的最低位是否为1,从而决定是否执行开关操作。

题解

#include<bits/stdc++.h>
using namespace std;

//2^16=65536 直接暴力枚举
//op表示每个位置的状态进行枚举
//最后判断是否全open
//使用vector记录路径

char g[4][4],bk[4][4];
typedef pair<int,int> PII;
vector<PII> res,tem;


void turn(int x,int  y)
{
    for(int i=0;i<4;i++)
    {
        if(g[i][y]=='-') g[i][y]='+';
        else g[i][y]='-';
    }
    
    for(int i=0;i<4;i++)
    {
        if(g[x][i]=='-') g[x][i]='+';
        else g[x][i]='-';
    }
    
    if(g[x][y]=='-') g[x][y]='+';
        else g[x][y]='-';  //两次没反过来,再反一次
    
}

int get(int i,int j)
{
    return i*4+j;
}

int main()
{
    for(int i=0;i<4;i++)
        cin>>g[i];
    
    for(int op=0;op<1<<16;op++) //16个位置的状态
    {
        memcpy(bk,g,sizeof g);
        
        //operation
        for(int i=0;i<=3;i++)
            for(int j=0;j<=3;j++)
                if(op>>get(i,j)&1) //该位置是1,进行反转
                    turn(i,j),tem.push_back({i,j});
        

        //judge
        int flag=0;

        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                if(g[i][j]=='+')
                    flag=1;
        
        //update            
        if(flag==0) //操作成功 全亮了
        {
            //如果方案为空或者他的操作数大于我们刚存好的新的方案,那么就修改它
            if(res.empty()||res.size()>tem.size()) res=tem;
        }
        
        tem.clear();
        
        
        //复原
        memcpy(g,bk,sizeof bk);
    }
    
    cout<<res.size()<<endl;
    
    for(int i=0;i<res.size();i++)
    {
        cout<<res[i].first+1<<' '<<res[i].second+1<<endl;
    }
    
    return 0;
}

Alt

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指针不指南吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值