【动态规划】最少按多少下开关使灯全亮

2023-11-09

无环条件下

题目描述

给定一个数组arr,长度为N,arr中的值不是0就是1

  • arr[i]表示第i栈灯的状态,0代表灭灯,1代表亮灯
  • 每一栈灯都有开关,但是按下i号灯的开关,会同时改变i-1、i、i+2栈灯的状态 (改变状态是指灯由原来的灭变亮和由原来的亮变灭)
    问题一:
  • 如果N栈灯排成一条直线,请问最少按下多少次开关,能让灯都亮起来
  • 排成一条直线说明:
  • i为中间位置时,i号灯的开关能影响i-1、i和i+1
  • 0号灯的开关只能影响0和1位置的灯
  • N-1号灯的开关只能影响N-2和N-1位置的灯

解题思路

还是使用动态规划的思想,主要是递推数组的定义,因为一个开关可以影响3个开关.

所以我们要让该递推数组带上三个状态,如当前的位置是i,那么我们就要记录一下i+1位置下标,前一个的状态preState,当前的状态curState.

有了这三个状态,我们后面才方便去根据前一个位置的状态去推当前的状态,这也就是动态规划的一个最基本的思想,就是开辟多个参数来记录不同的状态

具体的变化过程:

如果preState的状态为0,那么说明我们一定要按下当前i位置的开关.
如果preState的状态为1,那么我们就不需要按下当前的i位置的开关

上面的就是递推公式,对于临界情况:

如果i到达了arr.length-1,也就是i+1到arr.length了,那么我们就要判断preState和curState的状态是否相同了.此时默认前面的状态都是1

如果不相同,那么就没有机会全亮了,直接返回Integer.MAX_VALUE
如果相同,那么如果状态为1,返回0;如果状态为0,返回1

递归版本

public int noLoopMinStep1(int[] arr){  
    if(arr==null||arr.length==0)  
        return 0;  
    if(arr.length==1)  
        return arr[0]==1?0:1;  
    if(arr.length==2)  
        return arr[0]!=arr[1]?Integer.MAX_VALUE:arr[0]^1;  
    int p1=process(arr,2,arr[0],arr[1]);  
    int p2=process(arr,2,arr[0]^1,arr[1]);  
    if(p2!=Integer.MAX_VALUE)  
        p2++;  
    return Math.min(p1,p2);  
}  
public int process(int[] arr,int nextIndex,int preState,int curState){  
	//临界情况
    if(nextIndex==arr.length)  
        return preState!=curState?Integer.MAX_VALUE:preState^1;  
    if(preState==0){  
        curState^=1;  
        int cur=arr[nextIndex]^1;  
        int next=process(arr,nextIndex+1,curState,cur);  
        return next==Integer.MAX_VALUE?next:next+1;  
    }else{  
        return process(arr,nextIndex+1,curState,arr[nextIndex]);  
    }  
}

迭代版本

public int noLoopMinStep2(int[] arr){  
  
    if(arr==null||arr.length==0)  
        return 0;  
    if(arr.length==1)  
        return arr[0]==1?0:1;  
    if(arr.length==2)  
        return arr[0]!=arr[1]?Integer.MAX_VALUE:arr[0]^1;  
    int p1=process2(arr,arr[0],arr[1]);  
    int p2=process2(arr,arr[0]^1,arr[1]);  
    if(p2!=Integer.MAX_VALUE)  
        p2++;  
    return Math.min(p1,p2);  
}  
private int process2(int[] arr, int preState, int curState) {  
    int i=2;  
    int count=0;  
    while(i<arr.length){  
        if(preState==0){  
            count++;  
            preState=curState^1;  
            curState=arr[i++]^1;  
        }else {  
            preState=curState;  
            curState=arr[i++];  
        }  
    }  
    return preState!=curState?Integer.MAX_VALUE:(count+preState^1);  
}

有环状态下

题目描述

和前面的题目一样,不同的是收尾相连是一个环.

解题思路

加上了环之后,我们最大的问题就是修改0位置的时候会影响尾,修改尾的时候会影响头.对于其他位置的元素和没环的时候是一致的.

递归版本

主函数:
我们从2下标开始,是因为想要在递归中避开firstIndex的影响.所以在主函数中单独的对0和1下标进行更改.因为只有0和1会影响到firstIndex的值,从2开始之后都不会影响到firstIndex的值

public int LoopMinStep(int[] arr){  
  
    if(arr==null||arr.length==0)  
        return 0;  
    if(arr.length==1)  
        return arr[0]==1?0:1;  
    if(arr.length==2)  
        return arr[0]!=arr[1]?Integer.MAX_VALUE:arr[0]^1;  
    if(arr.length==3)  
        return arr[0]!=arr[1]||arr[1]!=arr[2]?Integer.MAX_VALUE:arr[0]^1;  
    //0不变 1不变  
    int p1=processForLoop(arr,3,arr[1],arr[2],arr[arr.length-1],arr[0]);  
    //0不变 1改变  
    int p2=processForLoop(arr,3,arr[1]^1,arr[2]^1,arr[arr.length-1],arr[0]^1);  
    //0改变 1不变  
    int p3=processForLoop(arr,3,arr[1]^1,arr[2],arr[arr.length-1]^1,arr[0]^1);  
    //0改变 1改变  
    int p4=processForLoop(arr,3,arr[1],arr[2]^1,arr[arr.length-1]^1,arr[0]);  
    p1=p1==Integer.MAX_VALUE?Integer.MAX_VALUE:p1++;  
    p2=p2==Integer.MAX_VALUE?Integer.MAX_VALUE:p2++;  
    p1=p3==Integer.MAX_VALUE?Integer.MAX_VALUE:p3++;  
    p1=p4==Integer.MAX_VALUE?Integer.MAX_VALUE:p4++;  
    return Math.min(Math.min(p1,p2),Math.min(p3,p4));  
}

因为有环的原因,所以我们又新加了两个状态firstState和endState.
当我们到达arr.length-2下标时,也就是nextIndex=arr.length-1时,会对endState有影响,这一点注意就好了

public int processForLoop(int[] arr,int nextIndex,int preState,int curState,int endState,int firstState){  
    //临界情况
    if(nextIndex==arr.length)  
        return (preState!=curState||curState!=firstState)?Integer.MAX_VALUE:endState^1;  
    if(preState==0){  
        int next=processForLoop(arr,nextIndex+1,curState^1,  
                                nextIndex==arr.length-1?endState^1:arr[nextIndex]^1,  
                                nextIndex==arr.length-1?endState^1:endState,firstState);  
        return next==Integer.MAX_VALUE?Integer.MAX_VALUE:next+1;  
    }else {  
        return processForLoop(arr,nextIndex+1,curState,arr[nextIndex], endState,firstState);  
    }
}

迭代版本

还是从i=3开始,还是要注意i=arr.length-1的时候的endState的值

public static int processForLoop(int[] arr,int preState,int curState,int endState,int firstState){  
    int i=3;  
    int op=0;  
    while (i<arr.length-1){  
        if(preState==0){  
            preState=curState^1;  
            curState=arr[i++]^1;  
            op++;  
        }else{  
            preState=curState;  
            curState=arr[i++];  
        }  
    }  
    //i==arr.length-1,也就是当前的位置在arr.length-2  
    if(preState==0){  
        op++;  
        preState=curState^1;  
        endState^=1;  
        curState=endState;  
    }else{  
        preState=curState;  
        curState=endState;  
    }  
    //i==arr.length了  
    return (preState!=curState||curState!=firstState)?Integer.MAX_VALUE:(op+curState^1);  
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【动态规划】最少按多少下开关使灯全亮 的相关文章

随机推荐

  • "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child raise child_exception OSError:

    在用KITTI数据时出错
  • Docker 高级篇

    文章目录 第一章 Docker复杂安装详说 1 1 安装mysql主从复制 1 2 安装redis集群 哈希槽分区进行亿级数据存储 1 2 1 相关面试题 1 2 2 集群搭建步骤 第二章 Dockerfile解析 2 1 是什么 2 2
  • 浅谈斜率优化

    DP模型 形如 f i max f j w i j quad 1 le j
  • PHP的弱类型比较

    php弱类型比较 php中其中两种比较符号 先将字符串类型转化成相同 再比较 先判断两种字符串的类型是否相等 再比较 前者为弱比较 后者为弱比较 若在某种情况下不注意利用会导致漏洞的出现 例子 攻防世界lottery 进入页面 浏览后查看
  • android studio常用快捷键设置

    android开发工具androidstudio的熟练使用是提高我们开发效率的必备条件 现对android studio使用过程中的一些小技巧进行总结 1 命名规范 android开发过程中使用java语言 对变量的命名遵循驼峰命名法 一般
  • Tracy JS 小笔记 - 数据类型, typeof,类型转换

    数据类型 原始值 引用值 原始值 不可改变的原始值 是存储在栈里面 stack 是个有底儿的箱子结构先进后出 原始值 分为五大类 Number Boolean String undefined null var a 1 我们数据的类型天生就
  • Apache Pig的一些基础概念及用法总结4(转)

    26 错误 ERROR org apache pig tools grunt Grunt ERROR 2042 Error in new logical plan Try Dpig usenewlogicalplan false 的可能原因
  • decltype和declval的用法

    1 decltype是c 11以后出现的一个新的关键字 是用来萃取表达式或者变量或者函数返回值的类型的 具体用法可以参考官网 https en cppreference com w cpp language decltype 2 declv
  • 华为-人民币转换

    java实现 题目描述 考试题目和要点 1 中文大写金额数字前应标明 人民币 字样 中文大写金额数字应用壹 贰 叁 肆 伍 陆 柒 捌 玖 拾 佰 仟 万 亿 元 角 分 零 整等字样填写 2 中文大写金额数字到 元 为止的 在 元 之后
  • xss基础知识点

    xss 1 概念 跨站脚本攻击 英文全称Cross Site Script xss攻击 通常指黑客通过 HTML注入 篡改了网页 插入了恶意的脚本 从而在用户浏览网页时 控制用户浏览器的一种攻击 常见场景 标签内的xss Xss 属性里面的
  • 安装Flutter + Android sdk + vs code运行Flutter项目(史上最详解)

    前言 Flutter开发app是基于Dart语言开发的 就好比html网页开发基于JavaScript一样 而浏览器内核都可以编译JavaScript代码 所有开发html网页不需要下载啥SDK 直接在浏览器就能运行 首先我们安装Dart语
  • python 用for i in range(10)生成列表

    这种方法叫列表解析 1 列出1 10的平方和 结果用列表存储 要求 列出1 10所有数字的平方 1 普通方法 L for i in range 1 11 L append i 2 print L 1 4 9 16 25 36 49 64 8
  • 如何实现通用分页(来看我这一篇就够了超级详细内含源码!!!)

    目录 一 页面显示分页效果 1 1分析页面展示所要展示的属性有哪些 1 2分析页面有哪些每次发送请求有哪些公共的参数 二 具体实现前端通用分页 2 1分析思路 2 2具体实现的过程 2 2 1标签助手类 2 2 2创建标签库描述文件 tld
  • QTableView获取选中行指定列的内容(新手上路)

    1 第一次用QT写东西 在tableview对象后面的函数列表里翻来翻去 找了个看起来顺眼的selectedRows来试图获取选中行的内容 然后插入到list里面 QList
  • TQ2440移植u-boot2016.11全过程记录-【5】设置从NOR FLASH启动U-BOOT

    TQ2440移植u boot2016 11 设置从NOR FLASH启动u boot gedit include configs tq2440 h 屏蔽掉宏CONFIG SKIP LOWLEVEL INIT 修改宏CONFIG SYS TE
  • ModelArts平台部署模型

    相关步骤 构建镜像 上传镜像至swr服务 模型管理建立模型 部署模型上线 调用接口 1 构建自定义镜像 基于Dockfile文件构建 文件准备及文件结构 关于深度学习中的概念 训练 train 以图像识别为例 基于一个标注好的数据集训练好了
  • React-基础语法

    React 基础语法 React 搭建脚手架 安装node JS 安装React脚手架 创建项目 运行项目 其他命令 使用VSCode 安装插件 基础插件 文档目录结构 根组件App js 解析 组件解析 类组件 有状态组件 函数组件 JS
  • 软件测试项目案例哪里找?【银行/教育/商城/金融/等等....】

    项目一 ShopNC商城 项目概况 ShopNC商城是一个电子商务B2C电商平台系统 功能强大 安全便捷 适合企业及个人快速构建个性化网上商城 包含PC IOS客户端 Adroid客户端 微商城 系统PC 后台是基于ThinkPHP MVC
  • ### Paper about Event Detection

    Paper about Event Detection author gr date 2014 03 15 email forgerui gmail com 看一些相关的论文 1 Efficient Visual Event Detecti
  • 【动态规划】最少按多少下开关使灯全亮

    文章目录 无环条件下 题目描述 解题思路 递归版本 迭代版本 有环状态下 题目描述 解题思路 递归版本 迭代版本 无环条件下 题目描述 给定一个数组arr 长度为N arr中的值不是0就是1 arr i 表示第i栈灯的状态 0代表灭灯 1代