电路布线问题动态规划详解(做题思路)

对于电路布线问题,想必学过动态规划的大家都很清除。今天就来讲解一下这个动态规划经典题目。

目录

    • 问题描述
    • 输入
    • 分析
    • 最优子结构
    • 代码

问题描述

在一块电路板的上、下2端分别有n个接线柱。根据电路设计,要求用导 线(i,π(i))将上端接线柱与下端接线柱相连,如图所示。其中π(i)是 {1,2,…,n}的一个排列。导线(i,π(i))称为该电路板上的第i条连线。对于任 何1≤i<j≤n,第i条连线和第j条连线相交的充分且必要的条件是π(i)>π(j)。 电路布线问题要确定将哪些连线安排在第一层上,使得该层上有尽可能 多的连线。换句话说,该问题要求确定导线集Nets={(i,π(i)),1≤i≤n}的最 大不相交子集。
在这里插入图片描述

输入

两行输入
第一行是一排接线柱的个数
第二行是上接线柱对应的下接线柱位置,即下文的p(i)
对于上图输入就是
10
3 1 2 4 7 9 5 6 10 8

分析

那么什么是最大不相交子集呢。咱们来一个一个字 的 扣含义。
首先最大就是字面意思最大的,最多的。
其次不相交也是字面意思,就是单纯的两条线不能有交点。
最后子集的定义是如果集合A的任意一个元素都是集合B的元素,那么集合A称为集合B的子集(通俗点说就是在给出的导线集合里面,挑选几条导线,这挑选的导线组成的集合就是子集)。
那么组合起来说的就是,在现有的线中挑选数量最多的导线且它们还不相交

我们发现这个题,好像不能从考虑最后一个步骤来推导了,我们好像还真不太好找出最后一个问题是什么。那么我们就换一种思路,回想以前的动态规划好像都是在数组中记录数值,供以后使用的而且都是一行一行的计算子问题。那我们先定义一个数组,考虑到有上下两排线,那就定义二维数组吧.。
设dp[i][j]表示前i个上接线柱和前j个下接线柱组成的问题的最优解包含的导线的数量(即前i个上接线柱和前j个下接线柱组成的集合的最大不相交子集中包含的导线数)

为了方便说明再来定义一些规则
上接线柱集合(1,2,3,4…n)
下接线柱集合(p(1),p(2),p(3),p(4)…p(n))
p(n)代表上层接线柱n对应的下层接线柱的编号。例如下图中上接线柱1,p(1)就是3

在这里插入图片描述

接下来以上图为例先从第一行来看,来找一下规律触发一下灵感
(第1步) i=1,j=1

在这里插入图片描述
(第2步) i=1,j=2

在这里插入图片描述
(第3步) i=1,j=3

在这里插入图片描述
唉突然发现此时,增加了一个,那就来想一想是什么原因让他增加的呢。我们发现当j>=p(1)时他就增加了,接下来继续看。
(第4步) i=1,j=3

然后类似的一直到 j==10 的时候
… …

(第10步) i=1,j=10
在这里插入图片描述
发现第一行除了j==3的时候增加了一个,其他的j>=p(1)的情况并没有增加为什么会这样呢?思考一下。因为我们的i是等于1的所以我们的dp[1][j]他最多只有一条线,我们上接线柱只包含了一个,所以他只能是小于等于一的数

这就给我们一个灵感我们可以根据i,p(i)的关系进行动态规划列出可能的情况加以分析

1.考虑当 i =1的时候
(1)j<p(i):肯定是零
(2)j>=p(i):他也肯定是一,因为这时最优解里面是空的,不用考虑香蕉🍌 (相交)的情况
2.考虑当 i>1时
(1)j<p(i):这时肯定还是不能包含这一条导线的,因为这一条导线的下接线柱没有被包含前 j 个里面。
那么这时他就相当于dp[i-1][j]。 为什么这么说呢?因为在j<p(i)时这一条导线是不可能被包含在我们的最优解里面的,所以就相当与这一条导线(i 导线)对于我们的当前的解是没有任何作用的。他就相当于是前 i -1个上接线柱和前 j 个下接线柱构成的问题的最优解。
也许此时聪明好学的你会问那为什么不是dp[i-1][j-1]呢?(即为什么不是前 i -1个上接线柱和前 j -1 个下接线柱构成的问题的最优解呢?。)
此时我们直接举一个一针见血的例子,如果i-1的下接线柱是 j 呢?dp[i-1][j-1]是不是就把第i-1条导线给漏掉了。
(2)j>=p(i): 这时候就说明我们可以包含这个导线,注意我说的是可以包含而不是一定包含。那么包含的条件是什么呢?想必你肯定已经知道了,就是当这条导线与最优解里面的导线都不香蕉🍌的时候 包含这个导线的最优解的个数比不包含这条导线的个数要大的时候才会包含 (dp[i][j]=Math.max(dp[i-1][p[i]-1]+1,dp[i-1][j])) 。而相交的时候就不可以包含了(dp[i][j]=dp[i-1][j])。

最优子结构

1.对与i<1的时候肯定是满足的,因为他的子问题不就是空的集合吗。
2.对于i>1的时候
(1)j<p(i) 它的最优解所包含的导线个数是是子问题的最优解dp[i-1][j]。假设子问题的最优解不是dp[i-1][j]而是R那么R>dp[i-1][j]所以原问题的最优解应该是R,这就矛盾了。
(2)j>=p(i) 的时候他的子问题是选择这一条导线(dp[i-1][p[i]-1]+1)或则不选这一条导线(dp[i][j]=dp[i-1][j])这两个中的最大值。对于不选择和上面的证明是一样的。
这里证明一下选择的情况:
在证明之前先了解一下子问题为什么是这个集合(前i-1个上接线柱,前p[i]-1个下接线柱)而不是其他的集合(例如前i-1个上接线柱,前j个下接线柱)。
我们既然选择了这一个导线就说明这个导线是不会与最优解里面的导线相交的。dp[i-1][p[i]-1]是前i-1个上接线柱,前p[i]-1个下接线柱 组成的解。我们的这一条导线对应的接线柱是i和p[i]。i>i-1且p[i]>p[i]-1所以他是这个集合中的最后一条线。就好比上图中的前4条导线,4是最后一条所以他肯定不
会与前三条相交的。

在这里插入图片描述

差不多理解了,就来证明最优子结构:
如果dp[i-1][p[i]-1]不是子问题的最优,最优的是R那么R+1>dp[i-1][p[i]-1]+1,所以由子问题构成的原问题的最优解应该是R+1而不是dp[i-1][p[i]-1]

代码

import java.util.Scanner;

public class AD {
    public static void MSN(int n,int[] p,int[][] dp){
        for(int i=1;i<=n;i++){

            for (int j=1;j<=n;j++){

                if(i<=1){

                    if(j<p[i]){
                        dp[i][j]=dp[i-1][j];
                    }else {
                        dp[i][j]=1;

                    }

                }else {

                    if(j<p[i]){
                        dp[i][j]=dp[i-1][j];
                    }else {
                        dp[i][j]=Math.max(dp[i-1][p[i]-1]+1,dp[i-1][j]);
                    }

                }

            }
        }
}

    public static void main(String[] args) {

        Scanner scanner=new Scanner(System.in);
        int n=scanner.nextInt();
        int[] p=new int[n+1];
        p[0]=0;
        for(int i=1;i<=n;i++){
            p[i]=scanner.nextInt();
        }
        int[][] dp=new int[n+1][n+1];

//        System.out.println(dp[n][n]);
        MSN(n,p,dp);

        System.out.println(dp[n][n]);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/120713.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RFSoC Debug:Petalinux 不显示 flash选项

这个板子和NI的X410是一样的。 问题 不显示Flash选项 [*] Advanced bootable images storage Settings ---> boot image settings ---> Image storage media (primary flash) --->解决 在Block Design中添加SD卡或者Flash选项&#xff0c;否则就不会显示&#xff1…

Linux驱动开发——USB设备驱动

目录 一、 USB 协议简介 二、 Linux USB 驱动 三、 USB 设备驱动实例 一、 USB 协议简介 USB(Universal Serial Bus&#xff0c;通用串行总线)正如它的名字一样&#xff0c;是用来连接PC外设的一种通用串行总线&#xff0c;即插即用和易扩展是它最大的特点。所谓即插即用&am…

软件测试怎么测别的类的main方法

软件测试怎么测别的类的main方法 🍎如果软测开发者题目待测类里有main方法,我们如何测? 可以采取以下步骤: 了解main函数的功能:首先,你需要了解这个main函数的功能和预期的输出。这样你才能设计出合适的测试用例。设计测试用例:设计测试用例时,需要考虑各种可能的输…

人工智能(AI)是一种快速发展的技术,其未来发展前景非常广阔。

人工智能&#xff08;AI&#xff09;是一种快速发展的技术&#xff0c;其未来发展前景非常广阔。以下是一些关于AI未来的可能发展方向和就业前景的详细说明&#xff1a; 1.机器学习工程师&#xff1a;机器学习是AI的核心技术之一&#xff0c;它涉及到从数据中自动学习模式并进…

一台电脑生成两个ssh,绑定两个GitHub账号

背景 一般一台电脑账号生成一个ssh绑定一个GitHub&#xff0c;即一一对应的关系&#xff01;我之前有一个账号也配置了ssh&#xff0c;但是我想经营两个GitHub账号&#xff0c;当我用https url clone新账号的仓库时&#xff0c;直接超时。所以想起了配置ssh。于是有了今天这篇…

一天吃透MySQL面试八股文

目录 事务的四大特性&#xff1f;数据库的三大范式事务隔离级别有哪些&#xff1f;生产环境数据库一般用的什么隔离级别呢&#xff1f;编码和字符集的关系utf8和utf8mb4的区别什么是索引&#xff1f;索引的优缺点&#xff1f;索引的作用&#xff1f;什么情况下需要建索引&…

【Linux】第十站:git和gdb的基本使用

文章目录 一、git的基本操作1.gitee新建仓库注意事项2.git的安装3.git的克隆4.git的add5.git的commit6.git的push7.git log8.git status9. .gitignore 二、Linux调试器---gdb1.背景2.gdb安装、进入与退出3.list/l4.r/run运行程序5. break/b 打断点6.info/i b 查看断点7.delete/…

2023年11月IDE流行度最新排名

点击查看最新IDE流行度最新排名&#xff08;每月更新&#xff09; 2023年11月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多&#xff0c;这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧&am…

csdn初始模板【自用】

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

【MongoDB-Redis-MySQL-Elasticsearch-Kibana-RabbitMQ-MinIO】Java全栈开发软件一网打尽

“Java全栈开发一网打尽&#xff1a;在Windows环境下探索技术世界的奇妙之旅” 前言 全栈开发是一项复杂而令人兴奋的任务&#xff0c;涵盖了从前端到后端、数据库到可视化层、消息队列到文件存储的广泛领域。本文将带您深入探讨在Windows环境下进行全栈开发的过程&#xff0…

金融帝国实验室(Capitalism Lab)推出一个密钥即完成注册机制!

为了方便趸购『金融帝国实验室』&#xff08;Capitalism Lab&#xff09;正版玩家&#xff0c;Enlight官方正式推出『一个密钥即完成注册』机制&#xff0c;切实简化游戏账户注册流程&#xff01; ————————————— 『一个密钥即完成注册』适用于趸购“游戏本体4DLC”…

LazyVim: 将 Neovim 升级为完整 IDE | 开源日报 No.67

curl/curl Stars: 31.5k License: NOASSERTION Curl 是一个命令行工具&#xff0c;用于通过 URL 语法传输数据。 核心优势和关键特点包括&#xff1a; 可在命令行中方便地进行数据传输支持多种协议 (HTTP、FTP 等)提供丰富的选项和参数来满足不同需求 kubernetes/ingress-n…

Oracle获取执行计划的6种方法

一、什么是执行计划&#xff1f; 执行计划是一条查询语句在Oracle中的执行过程或访问路径的描述。 执行计划描述了SQL引擎为执行SQL语句进行的操作&#xff0c;分析SQL语句相关的性能问题或仅仅质疑查询优化器的决定时&#xff0c;必须知道执行计划&#xff1b;所以执行计划常用…

oracle使用regexp_substr来拆分,CONNECT BY LEVEL查询卡死,速度慢的问题。

一、问题 oracle 使用regexp_substrCONNECT BY LEVEL来&#xff0c;根据特定字符拆分成多行。 &#xff08;注意这里我的数据是每个值都有“ ; ”&#xff0c;即使后面没有值&#xff0c;后面也会有个“ ; ”&#xff0c; 如果是正常的分隔符&#xff0c;sql 需要改成” LEVEL…

el-input-number输入框超过限制后自动变为最大值

input输入框使用了el-input-number 需求&#xff1a;目标室温输入框数据库设置最大是4位整数&#xff0c;限制一位小数&#xff0c;且后面要加单位&#xff0c;当输入数字超过限制&#xff0c;默认显示限制的最大值 &#xff0c;所以就有了输入完图一自动变为图二的数字。 el-i…

unittest 统计测试执行case总数,成功数量,失败数量,输出至文件,生成一个简易的html报告带饼图

这是一个Python的单元测试框架的示例代码&#xff0c;主要用于执行测试用例并生成测试报告。其中&#xff0c;通过unittest模块创建主测试类MainTestCase&#xff0c;并加载其他文件中的测试用例&#xff0c;统计用例的执行结果并将结果写入文件&#xff0c;最后生成一个简单的…

记录一次校园CTF--wp

一.第一题简单nc 这题直接nc 地址端口即可得到flags没有套路 二.第二题pwn:ezstack 这是一题栈溢出题目&#xff0c;查看保护&#xff1a; 没有开启PIE&#xff0c;运行下查看效果&#xff1a; 题目是一个文字购物游戏。 接着扔进IDA中分析&#xff1a; 在主函数中我们找到…

macOS电池续航工具:Endurance中文

Endurance for Mac是一款强大而实用的电池管理和优化软件&#xff0c;专为MacBook设计。通过智能调整系统设置和管理后台应用&#xff0c;它能有效延长电池续航时间&#xff0c;提升工作和娱乐效率&#xff0c;成为你在各种场合下的得力助手。 Endurance for Mac软件的功能特色…

cordova Xcode打包ios以及发布流程(ionic3适用)

第一步 1、申请iOS证书 2、导入证书到钥匙串 第二步 1、xcode配置iOS证书 1.1用Xcode打开你的项目&#xff08;我的Xcode版本是新版&#xff09; 修改如下图 回到基本信息设置界面&#xff0c;Bundie 这项填写&#xff0c;最先创建的那个appid&#xff0c;跟创建iOS描述文件时选…

MySQL基础架构详解

概述 我们学习东西&#xff0c;都不应该是先去了解细节&#xff0c;而是应该窥其全貌&#xff0c;这样才能从高纬度去理解问题&#xff0c;同样我们学习mysql也是一样的&#xff0c;我们应该先了解整个mysql架构&#xff0c;及来龙去脉&#xff0c;才能更好的掌握它。下面我们开…