飞行员兄弟,四种ac代码

【算法设计与分析】经典常考三十三道例题&AC代码 小虾目前大三,我校在大一下开设《数据结构》这门课,大二上开了《算法设计与分析》这门课,很庆幸这两门课的上机考试总成绩一门100,一门99,最后总分也都90+。下文会给出机试的33道题目&AC代码&注释供大家参考。 《算法设计与分析》用的是屈婉玲老师的教材,上机习题用的是王晓东前辈的,开授这门课的教授表示:考虑到算法具有一定的难度,并不适合所有的学生,只讲授和考察四个专题的内容(贪心、递归与分治、动态规划、回溯与分值限界) 阅读详情

题目描述:

“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有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

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

解法:

这里给出四种方法,我每个写完进行过测试,速度从满到快
在这里插入图片描述

1.数组写法,最慢的写法

利用一个char数组保存信息,循环枚举各种可能的方法

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>

#define x first
#define y second

using namespace std;

typedef pair<int,int> PII;

const int N = 5;

char bro[N][N] , backup[N][N];

int get(int x,int y ){
    return x*4+y;
}


void turn_one(int x,int y)
{
    if(bro[x][y] == '+') bro[x][y] = '-';
    else    bro[x][y] = '+';
}



void turn_all(int x,int y){
    for(int i = 0;i<4;i++)
    {
        turn_one(x,i);
        turn_one(i,y);
    }
    
    turn_one(x,y);
}



int main()
{
    for(int i = 0;i<4;i++)cin>>bro[i];
    
    vector<PII> res;
    for(int op = 0;op<1<<16;op++)
    {
        vector<PII> tmp;
        memcpy(backup,bro,sizeof bro);
        
        for(int i = 0;i<4;i++)
            for(int j = 0;j<4;j++)
                if(op>>get(i,j)&1)
                {
                    tmp.push_back({i,j});
                    turn_all(i,j);
                }
                
        bool has_close = false;
        for(int i =0;i<4;i++)
            for(int j = 0;j<4;j++)
                if(bro[i][j]=='+'){
                    has_close = true;
                    break;
                }
        if(has_close == false)
        {
            if(res.empty()||res.size()>tmp.size())res = tmp;
        }
        
        memcpy(bro,backup,sizeof bro);
        
    }
    
    cout<<res.size()<<endl;
    
    for(auto c:res)cout<<c.x+1<<' '<<c.y+1<<endl;
    
    return 0;
    
}

2.位优化,比数组快很多

利用一个16位的二进制数的每一位1/0来保存信息,适用于每个位置的信息只有两种情况的题目

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>

#define x first
#define y second

using namespace std;

typedef pair<int,int> PII;

const int N = 4;

int change[N][N];

int get(int x,int y ){
    return x*4+y;
}

int main()
{
    for(int i = 0;i<N;i++)
        for(int j = 0;j<N;j++)
        {
            for(int k = 0;k<N;k++) change[i][j] +=(1<<get(i,k)) + (1<<get(k,j));
            change[i][j] -= 1<<get(i,j);
        }
        
    int state = 0;
    
    for(int i = 0;i<4;i++){
        string s;
        cin>>s;
        for(int j = 0;j<4;j++) 
            if(s[j] == '+') state += 1<<get(i,j);
    }
    
    
    vector<PII> res;
    
    for(int k = 0;k<1<<16;k++)
    {
        int now = state;
        vector<PII> tmp;
        for(int i = 0;i<16;i++)
        {
            if(k>>i&1)
            {
                int a = i/4,b  = i%4;
                now ^= change[a][b];
                tmp.push_back({a,b});
            }
        }
        if(!now && (res.empty()||res.size()>tmp.size())) res = tmp;
    }
    cout<<res.size()<<endl;
    for(auto c:res)cout<<c.x+1<<' '<<c.y+1<<endl;
    
        
    return 0;
    
}

3.dfs,比枚举能优化十倍左右

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

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cstdio>

#define x first
#define y second

using namespace std;

typedef pair<int,int> PII;

const int N = 5;
char g[N][N];
vector<PII> res,tmp;

void turn_one(int x,int y)
{
    if(g[x][y]=='+')g[x][y] = '-';
    else g[x][y]='+';
}


void turn_all(int x,int y)
{
    for(int i = 0;i<4;i++)
    {
        turn_one(x,i);
        turn_one(i,y);
    }
    turn_one(x,y);
}



void dfs(int x,int y)
{
    if(x == 3 && y == 4)
    {
        bool success = true;
        for(int i = 0;i<4;i++)
            for(int j = 0; j <4;j++)
            if(g[i][j] == '+'){
                success = false;
                break;
            }
    
    if(success)
        if(res.empty()||tmp.size()<res.size())
            res = tmp;
    return;
    }
    
    if(y == 4)x++,y= 0;
    
    turn_all(x,y);
    tmp.push_back({x,y});
    dfs(x,y+1);
    
    tmp.pop_back();
    turn_all(x,y);
    
    dfs(x,y+1);
}


int main()
{
    for(int i = 0;i<4;i++)scanf("%s",g[i]);
    
    //从0,0开始DFS
    dfs(0,0);
    
    cout<<res.size()<<endl;
    for(auto c:res)cout<<c.x+1<<' '<<c.y+1<<endl;
    
        
    return 0;
    
}

4.dfs+位优化 ,实测比dfs还能快很多

在dfs的基础上加上位优化

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cstdio>

#define x first
#define y second

using namespace std;

typedef pair<int,int> PII;


const int N = 4;

int change[N][N];
vector<PII> res,tmp;
int state = 0;
int now;

int get(int x,int y ){
    return x*4+y;
}



void turn_all(int x,int y)
{
    
    now ^= change[x][y];
}



void dfs(int x,int y)
{
    if(x == 3 && y == 4)
    {
        bool success = true;
        if(now)
            {
                success = false;
            }
    
    if(success)
        if(res.empty()||tmp.size()<res.size())
            res = tmp;
    return;
    }
    
    if(y == 4)x++,y= 0;
    
    turn_all(x,y);
    tmp.push_back({x,y});
    dfs(x,y+1);
    
    tmp.pop_back();
    turn_all(x,y);
    
    dfs(x,y+1);
}


int main()
{
    
    for(int i = 0;i<N;i++)
        for(int j = 0;j<N;j++)
        {
            for(int k = 0;k<N;k++) change[i][j] +=(1<<get(i,k)) + (1<<get(k,j));
            change[i][j] -= 1<<get(i,j);
        }
    
    for(int i = 0;i<4;i++){
        string s;
        cin>>s;
        for(int j = 0;j<4;j++) 
            if(s[j] == '+') state += 1<<get(i,j);
    }
    
    now = state;
    
    //从0,0开始DFS
    dfs(0,0);
        
    cout<<res.size()<<endl;
    for(auto c:res)cout<<c.x+1<<' '<<c.y+1<<endl;
        
    return 0;
    
}
Acwing-蓝桥杯-116.飞行员兄弟 这道题目初看上去是一道通过上一个状态递推的问题,但是经过分析以后看出,这道题目每次改变一个把手所影响的其他把手太多,因此通过简单的递推并不能很快的找出规律。我们使用pair容器储存每次操作的步骤,分别使用两个vector容纳当前操作的所有步骤now和最小步数需要的步骤res,每次将res赋值为res和temp两者步骤更少的一个即可。因为每一个开关的操作都是有两种情况——操作或者不操作,因此可以使用位运算枚举所有的情况,最后判断每一种操作后所有的开关是否都已经被打开,如果都打开则可以纳入方案。 阅读详情

相关推荐

AC算法代码

AC算法 源代码包含算法原理

AC是什么意思?

AC就是accept,接受的意思,一般用在ONLINE JUDGE网上,表示能通过的代码。在刷算法题时,我们有时会接触一些“黑话”,类似上图。那么它们都是什么意思呢?(注:以下内容为从北京航空航天大学AC编程平台。常见的是AC、WA、TLE。

rt_tryqc的博客 6480

uva最全ac代码

uva最全ac代码

c++ AC 代码

题目获取方法: 打开浏览器,输入 “ http://1.14.136.201/problem.php?id ” 再加上 : 题目编号 (就是"Problem"后的四位数字(见下图)) AC代码: Problem1000: #include <bits/stdc++.h> using namespace std; int main(){ double a,b; scanf("%lf%lf",&a,&b); if(a>b){ printf(

wyz831201的博客 1817

CCF部分AC代码

CCF题目中能AC的渣代码,可用来对拍

CZT与FFT频谱分析方法对比:从任意频带重采样到高精度频谱分析

M = 85 % 输出点数f0 = 70 Hz % 起始频率DELF = 0.4 Hz % 频率步长频率分辨率提高到0.4 Hz分析带宽聚焦在[70, 103.6]Hz更清晰地分辨出78Hz和82Hz的频率分量。

2403_88098319的博客 1863

AcWing 116.飞行员兄弟(思路 + 代码详解)

暴力枚举

nuc_ghp的博客 632

SDFCOM_SWC警告深度剖析:从assign短路到时序标注失效的链路追踪

本文深入剖析了SDFCOM_SWC警告的根源,从assign短路到时序标注失效的全链路追踪。通过分析RTL设计中的assign语句陷阱、综合阶段的优化变形以及PrimeTime生成SDF文件的视角,提出了重构RTL设计、警告抑制和SDF生成优化等解决方案,帮助工程师有效避免时序标注问题。

weixin_42519985的博客 366

波动数列,简易AC代码,详细讲解。

波动数列 这道题真的是需要自己花时间来理解细节。 思路: 如下图所示,该序列的首项是x,公差为set,set={a,-b}; 通过下边的第一幅图我们可以知道,set的数量为n*(n-1)/2 (公式:首项加末项除以2) 我们令cnt=n*(n-1)/2 (也就是set的数量) 通过这些分析我们可以知道满足这么一个条件:序列总和=Sn=nx+cntset 我们假设a的数量为num1,因为a,b数量的总和是cnt,则b的数量就是cnt-num1; 可推出一个表达式nx+a * num1-b(cnt-nu

QNBZ的博客 1211

使用 Cadence ams 仿真器 对 混合信号电路 进行仿真

文章目录Cadence 基于ams仿真器的混合信号电路仿真建立数字(Digital)模块建立 Analog - Digital 混合仿真原理图建立 Analog - Digital 混合仿真config文件配置混合信号电路仿真环境针对混合信号电路demo进行仿真 Cadence 基于ams仿真器的混合信号电路仿真 你好,这里是一篇关于使用 Cadence 软件通过 ams 仿真器对混合信号电路(D...

mymatin1004的博客 2万+

Oracle11g安装教程、配置实例、监听、客户端程序详解_Windows篇

Oracle11g安装教程、配置实例、监听、客户端程序详解_Windows篇 文章目录Oracle11g安装教程、配置实例、监听、客户端程序详解_Windows篇前言一、数据库的安装前准备,前提是没有安装过!!!二、仅安装数据库软件(数据库运行环境)三、添加数据库实例四、设置监听程序,让数据库可以通过网络访问五、为目标数据库设置网名总结 前言 如果需要安装包:联系我看到会给你链接,因为现在官网已经不提供10g,11g的安装包了,在网盘保存望悉知(回复不会很及时,下班看到会回复敬请谅解)。 提示:以下

zhx__的博客 5632

C++飞行员兄弟(枚举)

“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。 已知每个把手可以处于以下两种状态之一:打开或关闭。 只有当所有把手都打开时,冰箱才会打开。 把手可以表示为一个4х4的矩阵,您可以改变任何一个位置[i,j]上把手的状态。 但是,这也会使得第i行和第j列上的所有把手的状态也随着改变。 请你求出打开冰箱所需的切换把手的次数最小值是多少。 输入格式 输入一共包含四行,每行包含四个把手的初始状态。 符号“+”表示把手处于闭合状态,而符号“-”表示把手处于打开状态。 至少一个手柄的初始状态是关闭的

星辰大海的博客 1126

点云从入门到精通技术详解100篇-点云的特征检测(续)

对每个维度的序列分别计算 DTW 距离,最后。权重将距离限制在较小的范围内,对于时间跨度大的数据集,过度限制了点对点的路径,同的,因此不能用欧氏距离来计算两个多元时间序列之间的距离,本文选用的是动态时。到的股票数据是未知分类的,因此该数据的相似性分析缺少有效的评价方式,通常需要。时间序列,简而言之,就是与时间相关的数据的集合,应用在生活工作中的方方面。时间序列的分段线性化表示的难点在于如何找出分段点,目前,对于分段点的研究。经过分段线性化之后,每个多元时间序列的维度是相同的,但是每一维的长度是不。

getusushu的博客 334

飞行员兄弟

飞行员兄弟 题目 “飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有 16 个把手的冰箱。 已知每个把手可以处于以下两种状态之一:打开或关闭。 只有当所有把手都打开时,冰箱才会打开。 把手可以表示为一个 4×4 的矩阵,您可以改变任何一个位置 [i,j][i,j] 上把手的状态。 但是,这也会使得第 i 行和第 j 列上的所有把手的状态也随着改变。 请你求出打开冰箱所需的切换把手的次数最小值是多少。 输入格式 输入一共包含四行,每行包含四个把手的初始状态。 符号 + 表示把手处于闭合状态,而符号 - 表示把

m0_53565874的博客 252

Android 16强制横竖屏设置

但开发者端的响应却相对滞后,特别是中小型开发团队受限于大屏设备市场渗透率(截至2023年Q2,Android平板全球激活量约1.2亿台,不足手机设备5%)及开发成本考量,适配优先级普遍偏低。这种适配滞后已形成恶性循环——开发者因设备基数不足降低适配意愿,而用户体验缺陷又反向抑制大屏设备的市场接受度。要破解这一困局,既需要Google持续优化Jetpack Compose等现代化UI工具链,更需要建立开发者激励体系,通过应用商店流量倾斜、开发补贴等经济手段提升适配投入产出比。再不肯好好适配大屏设备?

xiangzhihong8的专栏 980

智联招聘Python岗位数据采集:基于API请求的校园招聘信息爬取实战

本项目开发了一个智联招聘Python岗位校园招聘数据采集系统,采用requests库直接调用API接口获取结构化数据。系统通过分析API接口结构,配置完整的请求头、Cookie和身份验证参数,实现了10页数据的批量采集。采集内容包括工作名称、薪资范围、企业信息等10个关键字段,并存储为Excel格式。项目严格遵守网络爬虫规范,合理控制请求频率,数据仅用于技术学习和就业分析。技术实现涉及API逆向工程、JSON数据处理、防御性编程等核心技能,为学生职业规划和教育机构教学改革提供数据支持。

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 631

算法竞赛进阶指南 递推 飞行员兄弟

“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。 已知每个把手可以处于以下两种状态之一:打开或关闭。 只有当所有把手都打开时,冰箱才会打开。 把手可以表示为一个4х4的矩阵,您可以改变任何一个位置[i,j]上把手的状态。 但是,这也会使得第i行和第j列上的所有把手的状态也随着改变。 请你求出打开冰箱所需的切换把手的次数最小值是多少。 输入格式 输入一共包含四行,每行包含四个把...

EP的别三日 307

C#实现OPC客户端与S7-1200 PLC通信:工控场景稳定通信的实战指南(附完整代码)

标准化优先:OPC UA是工业通信的标准,相比直接通信,更适合多设备集成的工控场景;稳定性第一:必须封装断线重连、异常处理、资源释放逻辑,满足7×24小时运行需求;效率优化:高频采集场景优先用批量读写,避免单个变量频繁请求;细节把控:节点ID、变量类型、端口配置等细节是新手最容易踩坑的地方,建议先用UA Expert验证。这套代码和方案已在多个工业项目中落地,从单台S7-1200到多台S7-1200/1500集群,都能稳定运行。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1041

(开灯问题)(B - The Pilots Brothers' refrigerator)(洛谷T74791 飞行员兄弟)

B - The Pilots Brothers’ refrigerator The game “The Pilots Brothers: following the stripy elephant” has a quest where a player needs to open a refrigerator. There are 16 handles on the refrigerator do...

006 菜是原罪 的博客 1016

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

AcWing 116. 飞行员兄弟

飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有 16 个把手的冰箱。已知每个把手可以处于以下两种状态之一:打开或关闭。只有当所有把手都打开时,冰箱才会打开。把手可以表示为一个 4×4 的矩阵,您可以改变任何一个位置 [i,j] 上把手的状态。但是,这也会使得第 i 行和第 j 列上的所有把手的状态也随着改变。请你求出打开冰箱所需的切换把手的次数最小值是多少。

SandwichBK的博客 148

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++算法思维训练:从翻硬币、飞行员兄弟到费解的开关

在算法与数据结构的学习中,状态翻转类问题(如开关问题)是训练计算思维和建模能力的经典场景。这类问题的核心在于将现实中的状态变化抽象为数学模型,并利用计算机的高效计算特性求解。其基本原理通常涉及状态表示(如布尔值、位运算)、操作定义(如翻转、异或)以及目标状态的判定。从技术价值看,解决此类问题能深刻理解贪心策略、暴力枚举、递推与状态压缩等核心算法思想,并锻炼将复杂约束转化为确定性步骤的能力。在实际应用场景中,这些思维模式可延伸至游戏AI(如点亮所有灯)、硬件控制(如继电器开关优化)、网络协议(如错误校验与恢复

cumo3681的博客 529

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

acwing 飞行员兄弟——算法进阶指南

题目链接 文章目录思路:AC代码: 思路: 1 题目是4*4的矩阵,数据范围小,考虑暴力枚举 2 对矩阵标号 0 1 2 3 4 5 6 7 8 9 10 11 12 14 14 15 3 总共有16个位置,每一个位置要么选,要么不选,所以情况有2^16种,我们采用二进制枚举,从0~2 ^16-1,每一个整数看他的16位二进制数,对应位上有1就选。例如1二进制为:0000 0000 0000 0001,只有第一个位置有1,那么我们选第一个位置,把对应的行,对应的列改变 . 细节见代码 AC代码: //目

qq_45769627的博客 496

飞行员兄弟--算法竞赛进阶指南

题目描述: “飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。 已知每个把手可以处于以下两种状态之一:打开或关闭。 只有当所有把手都打开时,冰箱才会打开。 把手可以表示为一个4х4的矩阵,您可以改变任何一个位置[i,j]上把手的状态。 但是,这也会使得第i行和第j列上的所有把手的状态也随着改变。 请你求出打开冰箱所需的切换把手的次数最小值是多少。 输入格式: 入一共包含四行,每行...

azwcl的博客 494

0x01 内容总结与例题习题

目录内容总结与例题二进制状态压缩【例题】最短Hamilton路径(AcWing91)lowbit运算习题飞行员兄弟(AcWing116) 内容总结与例题 二进制状态压缩 有一些问题经常可以采用二进制状态压缩起来成为一个容易解决的问题。 常用的操作有: 取出整数nnn在二进制表示下的第kkk位:(n >> k) & 1 把整数nnn在二进制表示下的第kkk位取反:n ^ (1 << k) 对整数nnn在二进制表示下的第kkk位赋值1:n | (1 << k) 对整数

juruo_c的博客 410
上一篇: 寄!最能体现迭代思想的一道题,反转链表!【C++】
下一篇: 【Leetcode】剑指Offer 04. 二维数组中的查找 :利用二分快速查找有序数列
Andy in boots
博客等级 码龄7年 73粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值