首页 > 其他分享 >飞行员兄弟 费解的开关

飞行员兄弟 费解的开关

时间:2024-03-31 18:29:35浏览次数:18  
标签:int res 费解 ++ st 开关 把手 飞行员 include

标签:位运算 递推 枚举

费解的开关

枚举第一行的所有按法是用来减少步数的,我之前一直觉得从第二行直接看就好,但是从第二行开始其实就已经固定了最后的答案,这样的解不一定是最少的甚至可能超出范围而没有解。
所以,枚举第一行的意义是:不需要在意第一行的灯是灭是暗,只需把第一行的按法枚举一遍,也就是我们说的 “操作”,每个位置都有两种选择,按(用1表示)或者不按(用0表示),遍历这32种操作引发的情况,每一次再通过res = min(res, step);把最小步数存一下,就能找到最优解
Note:
枚举第一行时:1表示按一下,0表示不按(当然反过来也可以啦~看你)

:::info
作者:小张同学
链接:https://www.acwing.com/solution/content/8747/
来源:AcWing
:::

在遍历整个矩阵时:1是灯亮,0是灯灭
memcpy 可以用来复制数组,这里是先把原数组备份一下,然后对本数组操作,本次操作结束后,要再把备份数组还原回来,再进行下一次操作啦~
25 盏灯排成一个 5×5 的方形。
每一个灯都有一个开关,游戏者可以改变它的状态。
每一步,游戏者可以改变某一个灯的状态。
游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
我们用数字 11 表示一盏开着的灯,用数字 00 表示关着的灯。
下面这种状态

10111
01101
10111
10000
11011

在改变了最左上角的灯的状态后将变成:

01111
11101
10111
10000
11011

再改变它正中间的灯后状态将变成:

01111
11001
11001
10100
11011

给定一些游戏的初始状态,编写程序判断游戏者是否可能在 6 步以内使所有的灯都变亮。

输入格式

第一行输入正整数 n,代表数据中共有 n 个待解决的游戏初始状态。
以下若干行数据分为 n 组,每组数据有 5 行,每行 5 个字符。
每组数据描述了一个游戏的初始状态。
各组数据间用一个空行分隔。

输出格式

一共输出 n 行数据,每行有一个小于等于 6 的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。
对于某一个游戏初始状态,若 6 步以内无法使所有灯变亮,则输出 −1。

数据范围

0<n≤500

输入样例:
3
00111
01011
10001
11010
11100

11101
11101
11110
11111
11111

01111
11111
11111
11111
11111

输出样例:

3
2
-1
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 6;

char g[N][N], backup[N][N];
int dx[5] = { -1, 0, 1, 0, 0 }, dy[5] = { 0, 1, 0, -1, 0 };

void turn(int x, int y)
{
    for (int i = 0; i < 5; i++)
    {
        int a = x + dx[i], b = y + dy[i];
        if (a < 0 || a >= 5 || b < 0 || b >= 5) continue;
        g[a][b] ^= 1;
    }
}

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        for (int i = 0; i < 5; i++) 
             for (int j = 0; j < 5; j++)
                 cin >> g[i][j];

        int res = 0x3f3f3f;
        for (int op = 0; op < 32; op++)
        {
            memcpy(backup, g, sizeof g);
            int step = 0;
            for (int i = 0; i < 5; i++)
                if(op>>i&1)
                {
                    step++;
                    turn(0, i);
                }
            for (int i = 0; i < 4; i ++ )
                for (int j = 0; j < 5; j ++ )
                    if (g[i][j] == '0')
                    {
                        step ++ ;
                        turn(i + 1, j);
                    }
            bool success = false;
            for (int i = 0; i < 5; i ++ )
                if (g[4][i] == '0')
                {
                    success = true;
                    break;
                }

            if (!success) res = min(res, step);
            memcpy(g, backup, sizeof g);
        }

        if (res > 6) res = -1;

        cout << res << endl;
    }
    return 0;
}

飞行员兄弟

//一个把手改变,会使所在行列的所有把手全部反转
//特点:①在最优解里面每个把手只按一次,按两次没有区别,
//②按的顺序无关紧要,最终取决于这个把手按的次数!!!
//思考这个题可以递推出来吗? 答案是:很难
//可以想一想,前面的题都是通过某种顺序,每一次都是影响一个灯泡,但是这个题
//不能使用前面的办法,因为操作一次会影响好多灯泡。所以想一想朴素做法

//我们发现这个题的数据范围很小,所以尝试用暴力解决ac
//暴力思路:①16个开关,所有开关的状态数量想一想是多少? 答案是2^16!这个我感觉
//我这么笨还是可以想出来的,往后怎么想呢?
//状态数量即最大操作次数2^16(65536),既然也不大,那就①枚举所有的方案,
//然后按照这个方案来操作
//②如果可以实现把手全开,证明此方案合法
//③然后统计这个方案里面需要操作的把手数量
//④在所有能按的开关数量里取一个最小值
//ac
//输出方案注意:若两种方案步数相同,按字典序(先按横坐标排序,再按纵坐标排序)

:::info
作者:山雾
链接:https://www.acwing.com/solution/content/80128/
来源:AcWing
:::

“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有 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
#include <iostream>
#include<vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 15;
bool backup[N][N];
char g[N][N];
bool st[N][N],stt[N][N];
int res=0x3f3f3f;
void  turn(int x,int y){ //转换每行每列
    for(int i=0;i<4;i++)
    {
        if(st[i][y])st[i][y]=false;
        else st[i][y]=true;
    }
    for(int i=0;i<4;i++)
    {
        if(st[x][i])st[x][i]=false;
        else st[x][i]=true;
    }


}
void  solve(){
        //一共 2的16次方个状态
    for(int i=0;i<1<<16;i++){
        int ans=0;
        for(int j=0;j<16;j++){
            if(i>>j&1){
                if(st[j/4][j%4])st[j/4][j%4]=false;
                else st[j/4][j%4]=true;
                turn(j/4,j%4);
                ans++;
            }
        }
        bool success=true;
        for(int k=0;k<4;k++)
        {
            for(int j=0;j<4;j++)
            {
                if(st[k][j]==false)
                    success=false;
            }
        }
        if(success)
        {
            res=min(res,ans);
            cout<<res<<endl;
            for(int m=0;m<16;m++)
            {
                if(i>>m&1)
                {
                    cout<<m/4+1<<" "<<m%4+1<<endl;
                }
            }
        }
        memcpy(st,stt,sizeof st);
    }
}
int main(){
    memset(stt,true,sizeof stt);
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            cin>>g[i][j];
            if(g[i][j]=='+')stt[i][j]=false;
        }
    }
    solve();
    return 0;
}

标签:int,res,费解,++,st,开关,把手,飞行员,include
From: https://blog.csdn.net/2301_79656184/article/details/137205803

相关文章

  • Verilog语法回顾--门级和开关级模型
    目录门和开关的声明门和开关类型支持驱动强度的门延迟实例数组and,nand,nor,or,xor,xnorbuf,notbufif1,bufif0,notif1,notif0MOSswitchesBidirectionalpassswitchespullup,pulldown参考《Verilog 编程艺术》魏家明著Verilog共有14中逻辑门和12种开关,用于提供门级和开关......
  • 区间开关灯模型
    P3870[TJOI2009]开关先看一道经典的区间开关灯问题的模型,维护一个lz每次异或操作就好了#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<int,int>;constintN=1e5+10;constintinf=0x3f3f3f3f;constintmod=1e9+......
  • Android Switch开关按钮使用和自定义样式
    最终效果minHeight,switchMinWidth调整switch开关高度、宽度android:thumb开关按钮上原型滑块的样式android:track开关按钮下面导轨的样式<Switchandroid:layout_width="48dp"android:layout_height="24dp"android:layout_marginEnd="21dp"......
  • C# winform窗口打开关闭后不释放内存问题
    问题解决一:如果是窗体属性加载了背景图导致的内存占用,在关闭窗体前,释放掉背景图资源即可释放占用的内存privateImagebackgroundImage;publicForm2(){InitializeComponent();backgroundImage=Image.FromFile(@"D:\XX......
  • GBU3510-ASEMI开关电源整流桥GBU3510
    编辑:llGBU3510-ASEMI开关电源整流桥GBU3510型号:GBU3510品牌:ASEMI封装:GBU-4平均正向整流电流(Id):35A最大反向击穿电压(VRM):1000V产品引线数量:4产品内部芯片个数:4产品内部芯片尺寸:160MIL峰值正向漏电流:<10ua恢复时间:>2000ns正向浪涌电流:350A正向压降:1.05V恢复时间:工作结温......
  • GBU3010-ASEMI开关电源整流桥GBU3010
    编辑:llGBU3010-ASEMI开关电源整流桥GBU3010型号:GBU3010品牌:ASEMI封装:GBU-4特性:插件、整流桥平均正向整流电流(Id):30A最大反向击穿电压(VRM):1000V恢复时间:>2000ns最大RMS电压:引脚数量:4芯片个数:4最大正向压降:1.05V芯片尺寸:160MIL工作温度:-55℃~150℃正向浪涌电流:300A类型......
  • 8. 基于51单片机的感应震动&按键&超声波&蜂鸣器开关盖桶
    项目概述功能描述检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖硬件说明SG90舵机,超声波模块,震动传感器,蜂鸣器链接:7.PWM开发SG90(手把手教会)链接:6.超声波测距的使......
  • 安卓14谷歌GooglePlay商店安装 谷歌基础服务打开 GMS服务开关 谷歌三件套安装
    环境:最新的安卓手机已经内置了谷歌三件套例如小米手机打开Go安装器可以看到结果,但是为什么没有Play商店的桌面进入图标呢,因为默认厂商把图标给隐藏了,只需要重新打开即可。提示安装Google服务后系统会增加显著的耗电,不用时建议关闭GMS服务添加快捷方式(使用其他软件)主程序......
  • yml文件-动态开关
    本质:${}读取字符串方案一增加一个属性swith来判断业务流走向//test.swith是配置文件中定义的参数@value("${test.swith}")Stringswith;publicvoidfunc(){if("on".equals(swith)){//执行对应的定时任务代码}} 方案二通过@ConditionalOnProperty......
  • 一加3T三段式开关切换 openpilot 版本
    一加3T三段式开关切换openpilot版本 修改continue.sh 文件如下 通过SSH登录到EON中,把openpilot不同版本的代码克隆到 /data/forks 目录下,然后根据自己的需求修改 PATH_FORK_{N} 的路径即可。修改文件存储目录:第4行修改不同版本OP目录:5~7行(分别对应三段......