5.11回溯法--电路板排列问题--排列树

news2024/12/23 6:05:24

问题描述

 将n块电路板以最佳排列插入带有n个插槽的机箱中,要求对于给定的电路板连接块,确定最佳排列,使其具有最小的密度。设x[ ] 表示n块电路板的一个排列,x[ i ]表示在机箱的第 i 个插槽中插入电路板x[ i ],x确定的电路板排列密度定义为:跨越相邻线路板插槽的最大连接数。如图5-9,这种电路板排列方案的密度为2。

 问题分析

电路板的最佳排列问题的解空间是典型的排列树。分清电路板和连接块这两个概念。

 

首先定义初始化变量

输入:int B[n][n]表示输入,B[i][j]=1表示电路板 i 在连接块 j 中

int total[ j ]是连接块Nj的电路板数量,就是这个连接块跨越了多少个电路板

电路板当前排列方案记录在x[1:i]中,当前解

now[j]表示在x[1:i]中包含的连接块Nj中的电路板的数量,这个用来判断插槽 i 和 i+1之间的连线数量,如果连接块Nj的连线跨越插槽 i 和 i+1 ,那么now[ j ] != total[ j ] && now[ j ] >0

然后就是最有解的一些变量,bestx[ ] 数组存放最优解 ,bestd表示最优密度

回溯主函数

 伪代码

 

 完整代码

#include <iostream>
#include <cstring> //memset头文件
#include <string.h>
using namespace std;
#define MAX 10

int x[MAX];        //当前电路板排列
int bestx[MAX];    //最优电路板排列
int n;             //电路板个数
int bestd = 10000; //最优密度,电路板密度为跨越相邻电路板最多连线数
int m;             //连接块数
int total[MAX];    // total[j]表示连接块j中电路板的个数
int now[MAX];      // now[j]表示当前解下,连接块j中电路板的个数
int b[9][6];       //连接块数组

void swap(int &a, int &b){
    int temp = a;
    a = b;
    b = temp;
}

//搜索排列树
//第i个电路板,当前排列密度为cd
void backtrack(int i, int cd){
    if (i == n) //当到达叶结点
    {
        bestd = cd; //算法仅完成比当前解更优的解,所以cd肯定优于bestd
        cout << "bestd= " << bestd << endl;
        memcpy(bestx, x, sizeof(x)); //拷贝最优解向量
    }
    else{
        for (int j = i; j <= n; j++) //下一步选哪个电路板
        {
            //计算增加了电路板x[j]后的连线密度
            int ld = 0;
            for (int k = 1; k <= m; k++)
            {
                now[k] += b[x[j]][k];                 //计算当前包含在连接块k中的电路板个数
                if (now[k] > 0 && now[k] != total[k]) //满足此条件
                    ld++;                             //连线密度增加
            }
            if (cd > ld) //更新ld
                ld = cd;
            if (ld < bestd) //如果当前连线密度小于最优值,才可能产生最优值,搜索子树
            {
                swap(x[i], x[j]);
                cout << "ninininini" << endl;
                backtrack(i + 1, ld); //搜索下一个结点
                swap(x[i], x[j]);
            }
            //恢复状态,为返回上一层做准备
            for (int k = 1; k <= m; k++)
            {
                now[k] -= b[x[j]][k];
            }
        }
    }
}

int main(){
    n = 8; //电路板数
    m = 5; //连接块数
    //初始化的输入矩阵信息
    b[9][6] = {
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 1, 0, 0},
        {0, 0, 1, 0, 0, 0},
        {0, 0, 1, 1, 1, 0},
        {0, 1, 0, 0, 0, 0},
        {0, 1, 0, 0, 0, 0},
        {0, 1, 0, 0, 1, 0},
        {0, 0, 0, 0, 0, 1},
        {0, 0, 0, 0, 0, 1}};
    memset(now, 0, sizeof(now));
    memset(total, 0, sizeof(total));
    //初始化x为单位排列并计算total
    for (int i = 1; i <= n; i++)
    {
        x[i] = i;
        for (int j = 1; j <= m; j++)
            total[j] += b[i][j];
    }

    backtrack(1, 0);

    printf("电路板个数:%d\n", n);
    printf("连接块个数:%d\n", m);
    printf("连接块情况:\n");
    printf("N1={4,5,6},N2={2,3},N3={1,3},N4={3,6},N5={7,8}\n");
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
            printf("%d ", b[i][j]);
        printf("\n");
    }
    printf("最优密度为:%d\n", bestd);
    printf("最优排列为:\n");
    for (int i = 1; i <= n; i++)
        printf("%d ", bestx[i]);
    printf("\n");
    return 0;
}

时间复杂度分析

解空间排列树每个节点,backtrack函数花费O(m)时间为每个儿子节点计算密度,计算密度耗费总时间O(m n!),生成排列树需要O(n!)时间,每次更新当前最优解至少使得bestd-1,算法运行结束时,bestd>=0,因此最优解更新次数为O(m),更新最优解需要O(mn)的时间

综上,电路板排列问题计算时间为O(m n!)

分析结束,晚安

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

尚硅谷ES6李强笔记

1.课程介绍 1.es是什么 2.新特性的优点 3.学习课程必备知识背景 2.相关名词介绍 3. let变量声明以及声明特性 3.1变量声明方式 //普通声明 let a;//一次性声明多个变量 let a,b,c;//声明并且初始化 let a 100;//一次性声明多个并且初始化 let a2,b1,ci love you;3.2不允许重…

打工人必学的法律知识(一)——《中华人民共和国劳动合同法》必知必会

目录 一、劳动合同无效或者部分无效 二、竞业限制 三、劳动合同的履行和变更 四、劳动合同的解除和终止 一、劳动合同无效或者部分无效 第二十六条 下列劳动合同无效或者部分无效&#xff1a;&#xff08;一&#xff09;以欺诈、胁迫的手段或者乘人之危&#xff0c;使对方…

使用FFmpeg命令处理音视频

文章目录前言一、ffprobe相关命令1.使用ffprobe查看音频文件的信息2.使用ffprobe查看视频文件的信息二、ffplay相关命令1.基本的ffplay命令2.音视频同步命令三、ffmpeg相关命令1.ffmpeg通用参数2.ffmpeg视频参数3.ffmpeg音频参数4.ffmpeg示例总结前言 FFmpeg是一套可以用来记录…

【C语言】字符函数,字符串函数,内存函数及其模拟实现

文章目录求字符串长度strlen长度不受限制的字符串函数strcpystrcatstrcmp长度受限制的字符串函数strncpystrncatstrncmp字符串查找函数strstrstrtokstrerror字符函数字符分类函数字符转换函数内存操作函数memcpymemmovememsetmemcmp求字符串长度 strlen 函数功能 求字符串长…

【机器学习之模型融合】Voting投票法简单实践

目录 前言&#x1f49c; 1、使用sklearn实现投票法&#x1f494; 1.1、导入工具库&#xff0c;准备数据&#x1f495; 1.2、定义交叉验证评估函数&#x1f496; 1.3、建立基于交叉验证的benchmark、做模型选择&#x1f31f; 1.4、构建多组分类器、进行融合&#x1f4a5;…

单线程的Node.js能开发高并发服务器程序吗?

文章目录前言Nodejs的事件驱动机制EventLoop vs NSRunLoopNSRunLoopios next runloop异步/事件循坏机制的那些坑批量迁移数据原子性参考文献前言 这篇文章还是从一个在写Node.js程序中遇到的问题说起。本周在做数据库迁移的时候&#xff0c;写了下面一段代码&#xff0c;目的是…

代数与逻辑:作业四 神经网络

代数与逻辑&#xff1a;作业四 神经网络 文章目录代数与逻辑&#xff1a;作业四 神经网络一、作业要求二、简述神经网络模型三、编程实现感知机模型与二隐层神经网络1、感知机模型2、二隐层神经网络四、选择公开数据集&#xff0c;测试感知机模型与二隐层神经网络性能一、作业要…

如何高效学习?一年学完麻省理工4年计算机课程

斯科特.杨用用10天拿下线性代数&#xff0c;用1年时间学完麻省理工大学4年的计算机课程&#xff0c;他是如何做到的&#xff1f;他在这本书《如何高效学习》中做了具体阐述。 斯科特.杨很早就发现&#xff0c;在美国有一半的学生在死记硬背&#xff0c;这些学生并不知道使用整体…

动手学区块链学习笔记(二):区块链以及工作量证明算法

引言 紧接上文&#xff0c;在介绍完区块链中的加密解密以及公钥私钥等算法后&#xff0c;本篇开始正式进入区块链概念与一个简单区块链系统的实现过程介绍。 区块链技术介绍 什么是区块链&#xff1f; 区块链&#xff0c;就是一个又一个区块组成的链条。每一个区块中保存了一…

制造企业数据/经营分析框架

背景 随着大数据技术发展以及数字化转型概念的普及&#xff0c;传统企业特别是制造业&#xff0c;也开始投入人力、资金&#xff0c;建立自己的数据分析团队&#xff0c;期望通过数据分析赋能企业的发展/转型。尽管&#xff0c;国内华为、美的、海尔、三一、徐工等制造业龙头企…

挡不住,逃不过,还是阳了

自从放开后&#xff0c;身边的&#x1f40f;陆陆续续多了起来。现在都不敢在食堂吃饭了&#xff0c;每次都是打包到工位吃&#xff0c;上班时也是都戴着口罩。每天回家后都是一顿扫射&#xff0c;用医用酒精做全身消毒。但是&#xff0c;还是没挡住&#xff0c;该来的还是来了。…

Leetcode:450. 删除二叉搜索树中的节点(C++)

目录 问题描述&#xff1a; 实现代码与解析&#xff1a; 递归&#xff1a; 原理思路&#xff1a; 含有内存释放版&#xff1a; 问题描述&#xff1a; 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜…

Day860.高性能数据库连接池HiKariCP -Java 并发编程实战

高性能数据库连接池HiKariCP Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于高性能数据库连接池HiKariCP的内容。 实际工作中&#xff0c;总会难免和数据库打交道&#xff1b; 只要和数据库打交道&#xff0c;就免不了使用数据库连接池。 业界知名的数据库连接池…

2023/1/15 JS-作用域与作用域链

1 作用域 理解 - 就是一块"地盘", 一个代码段所在的区域&#xff0c;它是静态的(相对于上下文对象), 在编写代码时就确定了 分类&#xff1a; 全局作用域函数作用域 没有块作用域(ES6有了) -->(java语言也有) if (true) {var a 3}console.log(a); // 3作用&am…

用互联网思维做产品,做超出用户预期的产品

做出超出用户预期的产品&#xff0c;做出让用户惊喜和兴奋的产品。超越用户期望极致体验极致服务极致产品(极致产品功能情感温度)关心、关注、尊重用户理解用户理解人性用户参与。只有深刻了解&#xff0c;深刻理解用户&#xff0c;深刻理解人性&#xff0c;才能做出好的产品。…

Maven安装教程讲解

目录一、下载安装JDK二、下载 Maven三、配置 Maven 环境变量四、配置 Maven 仓库地址五、配置 Maven 镜像六、配置 Maven JDK七、IDE配置 Maven八、IDE新建 Maven 项目九、IDE执行 Maven 命令一、下载安装JDK 教程&#xff1a;https://blog.csdn.net/weixin_43888891/article/…

【阶段四】Python深度学习09篇:深度学习项目实战:循环神经网络处理时序数据项目实战:CNN和RNN组合模型

本篇的思维导图: 项目背景 时间序列数据集中的所有数据都伴随着一个时戳,比如股票、天气数据。这个数据集,是科学家们多年间用开普勒天文望远镜观察并记录下来的银河系中的一些恒星的亮度。广袤的宇宙,浩瀚的星空在过去很长一段时间里,人类是没有办法证明系外行星…

关于一次python服务性能的问题分析定位

今天项目遇到一个比较棘手的问题&#xff0c;我们做的接口平台&#xff0c;提供了一个给用户自己编辑关键字的逻辑&#xff0c;发现对应服务的cpu基本都满了&#xff0c;并且通过扩容的方式也没有好转&#xff0c;也同样被打满。 找了测试的同学了解了下&#xff0c;发现他们使…

Enterprise JavaBean 简介

Enterprise JavaBean 简介 在顶层我们使用的框架是面向服务的&#xff0c;而在其之下的开发方法面向组件&#xff0c;最基层的便是面向对象面向过程的JAVA编程。 面向过程和面向对象是两种具体程序设计时的编程范式&#xff0c;他们没有本质区别&#xff0c;只是使用不同的方…

【Linux】Linux命令行git和Linux调试器-gdb的使用

文章目录一、Linux命令行git1. git是什么2. Gitee上创建仓库&#xff0c;克隆仓库到本地3. git三板斧二、Linux调试器-gdb的使用1. debug和release的区别2. 常用命令一、Linux命令行git 1. git是什么 git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很…