UVa 690 Pipeline Scheduling 流水线调度 二进制表示状态 DFS 剪枝

news2024/9/20 8:46:57

题目链接:Pipeline Scheduling
题目描述:

给定一张 5 × n ( 1 ≤ n ≤ 20 ) 5\times n(1\le n\le20) 5×n(1n20)的资源需求表,第 i i i行第 j j j列的值为’X’表示进程在 j j j时刻需要使用使用资源 i i i,如果为’.'则表示不需要使用。你的任务是安排十个相同进程的启动时间,使得所有进程完成的时间尽可能的早。在安排每个进程的开始时间你需要注意:

  • 一个进程一旦开始就必须要一直执行,而不能停止;
  • 任意一个资源必须进行互斥使用,也就是任意时刻 j j j需要保证对于 1 ≤ i ≤ 5 1\le i\le5 1i5 i i i资源最多只被一个进程所使用。

你需要输出最早的完成时间。
例如输入为:
在这里插入图片描述
对应的输出应该是 34 34 34,对应的每个进程的执行情况如下表(图中的编号代表进程的编号):
在这里插入图片描述

题解:

本题不难想到的暴力方法是,枚举十个进程的开始时间,由于一共有十个进程每个进程开始的时间范围为: [ 0 , n ] [0, n] [0,n],所以时间复杂度为 O ( n 10 ) O(n^{10}) O(n10)
这样需要枚举的状态太多了,如何减少状态呢?在我们已知每个资源关于时间的需求情况实际上我们可以知道并不是 [ 0 , n ] [0, n] [0,n]所有的开始时间都是可行的,我们能够确定出有限个可行的开始时间。我们设当前进程相对于上一个进程晚开始 d e l a y T i m e delayTime delayTime,那么此时当前的进程会在那些时刻占用那些资源是可以确定的,而只有当前进程占用的资源与上一个进程占用的资源不存在冲突的时候 d e l a y T i m e delayTime delayTime才是可行的,如果能够提前计算出所有的 d e l a y T i m e delayTime delayTime,那么最后进行枚举的时候复杂度就会大大减少。
如何快速判断一个 d e l a y T i m e delayTime delayTime是否可行?我们可以用二进制来保存每个资源与时间的关系,例如样例的输入我们可以用二进制表示为:
s t a t u s [ 0 ] = 0110001 s t a t u s [ 1 ] = 0000010 s t a t u s [ 2 ] = 0000100 s t a t u s [ 3 ] = 0001000 s t a t u s [ 4 ] = 1000000 status[0] = 0110001\\ status[1] = 0000010\\ status[2] = 0000100\\ status[3] = 0001000\\ status[4] = 1000000 status[0]=0110001status[1]=0000010status[2]=0000100status[3]=0001000status[4]=1000000
而当前进程相对于上一个进程延迟 d e l a y T i m e delayTime delayTime后开始,那么上一个进程在当前进程的各个资源占用会产生影响的部分实际上是 s t a t u s [ i ] > > d e l a y T i m e status[i] >> delayTime status[i]>>delayTime(注意这里使用的二进制表示和图上是颠倒的,所以此处需要用右移表示时间的流逝,而如果不颠倒处理需要进行特定的位数判断比较麻烦),而当前进程的资源使用情况就是 s t a t u s [ i ] status[i] status[i],所以只要KaTeX parse error: Expected 'EOF', got '&' at position 11: status[i] &̲ (status[i] >>d…就代表资源 i i i不会发生冲突,只有五个资源都不发生冲突的 d e l a y T i m e delayTime delayTime才是可行的。
还有剪枝方法吗?实际上这样应该能够通过大部分数据,但是我们还有一个比较简单的剪枝,但是这个剪枝能够去除掉很多的状态。我们需要记录一个 m i n D e l a y T i m e minDelayTime minDelayTime表示所有 d e l a y T i m e delayTime delayTime中的最小值,如果 n o w S t a r t T i m e + r e s t P r o c e s s N u m × m i n D e l a y T i m e + n ≥ n o w A n s nowStartTime + restProcessNum \times minDelayTime + n \ge nowAns nowStartTime+restProcessNum×minDelayTime+nnowAns,那么我们直接进行剪枝即可(即假设后续所有的进程都能最早开始但是依然不能早于当前记录的答案时进行减值)。

代码:

#include <bits/stdc++.h>

const int INF = 0x3f3f3f3f;
const int UNIT_NUM = 5;
const int PROCESS_NUM = 10;

using namespace std;

int ans, n, minDelayTime;
int status[UNIT_NUM];
string reservationTable;
vector<int> nextStep;

void init()
{
    nextStep.resize(0);
    ans = INF;
    minDelayTime = -1;
    for (int delayTime = 1; delayTime <= n; delayTime++) {
        bool canStart = true;
        for (int unitID = 0; unitID < UNIT_NUM; unitID++) {
            if ((status[unitID] >> delayTime) & status[unitID]) {
                canStart = false;
                break;
            }
        }
        if (canStart) {
            if (minDelayTime == -1) { minDelayTime = delayTime; }
            nextStep.push_back(delayTime);
        }
    }
}

void dfs(int nowDepth, int nowStartTime, int s0, int s1, int s2, int s3, int s4) {
    if (nowDepth == PROCESS_NUM - 1) { // 这里等于PROCESS_NUM - 1是因为0号进程已经安排到0时刻开始,后续安排的是1-9号进程
        ans = min(ans, nowStartTime + n);
        return ;
    }
    if (nowStartTime + (9 - nowDepth) * minDelayTime + n >= ans) { return; }
    for (int delayTime : nextStep) {
        int ns0 = s0 >> delayTime, ns1 = s1 >> delayTime, ns2 = s2 >> delayTime, ns3 = s3 >> delayTime, ns4 = s4 >> delayTime;
        if ((ns0 & status[0]) || (ns1 & status[1]) || (ns2 & status[2]) || (ns3 & status[3]) || (ns4 & status[4])) {continue; }
        dfs(nowDepth + 1, nowStartTime + delayTime, ns0 | status[0], ns1 | status[1], ns2 | status[2], ns3 | status[3], ns4 | status[4]);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    while (cin >> n && n != 0) {
        for (int i = 0; i < UNIT_NUM; i++) {
            cin >> reservationTable;
            status[i] = 0;
            for (int j = 0; j < n; j++) {
                if (reservationTable[j] == 'X') {
                    status[i] |= 1 << j;
                }
            }
        }
        init();
        dfs(0, 0, status[0], status[1], status[2], status[3], status[4]);
        cout << ans << endl;
    }
    return 0;
}

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

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

相关文章

多元化增长引擎业务占比超四成,联想开启混动模式?

一句话概括联想集团的业绩&#xff1a;预料之内的整体下滑&#xff0c;超出预期的第二曲线。 上周五&#xff08;2月17日&#xff09;&#xff0c;联想集团发布了2022到2023财年第三季度业绩。根据财报&#xff0c;联想集团实现营收152.67亿美元&#xff0c;同比下降24%&#…

你评论,我赠书~【哈士奇赠书 - 14期】-〖人人都离不开的算法-图解算法应用〗参与评论,即可有机获得

大家好&#xff0c;我是 哈士奇 &#xff0c;一位工作了十年的"技术混子"&#xff0c; 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 &#x1f4ac; 人生格言&#xff1a;优于别人,并不高贵,真正的高贵应该是优于过去的自己。&#x1f4ac; &#x1f4e…

html常用font-family设置字体样式

<table border"1" cellpadding"0" cellspacing"0" ><tr><td><h3 style"font-family: 黑体;">黑体&#xff1a;SimHei</h3></td><td><h3 style"font-family: 华文黑体;">华…

优思学院:六西格玛中的水平对比方法是什么?

水平对比&#xff0c;就是比较不同事物之间的差异。 这个概念在六西格玛管理中也很重要&#xff0c;也就是我们经常说的标杆管理&#xff0c;经常被用来寻找行业中最好的做法&#xff0c;以帮助组织改进自身的绩效。 在六西格玛管理中&#xff0c;水平对比有三种常见的应用方式…

java面试题-JUC基础类介绍

1.JUC框架包含几个部分?五个部分&#xff1a;Lock框架和Tools类(把图中这两个放到一起理解)Collections: 并发集合Atomic: 原子类Executors: 线程池2.Lock框架和Tools哪些核心的类?Lock接口&#xff1a;用于提供比synchronized更加灵活和高级的线程同步控制&#xff0c;支持公…

<Linux>vscode搭建Linux远程开发工具

一、下载vscode&#x1f603;可以去vscode的官网下载&#xff0c;不过是外网下载速度较慢提速可以参考&#xff1a;(81条消息) 解决VsCode下载慢问题_vscode下载太慢_wang13679201813的博客-CSDN博客官网&#xff1a;Visual Studio Code - Code Editing. Redefined这里推荐的是…

【自然语言处理】【大模型】GLM-130B:一个开源双语预训练语言模型

GLM-130B&#xff1a;一个开源双语预训练语言模型《GLM-130B: An open bilingual pre-trained model》论文&#xff1a;https://arxiv.org/pdf/2210.02414.pdf 相关博客 【自然语言处理】【大模型】GLM-130B&#xff1a;一个开源双语预训练语言模型 【自然语言处理】【大模型】…

拼多多出评软件工具榜单助手使用教程

软件使用教程下载软件前&#xff0c;关闭电脑的防火墙&#xff0c;退出所有杀毒软件&#xff0c;防止刷单软件被误删桌面建立一个文件夹&#xff0c;下载下来的安装包放进去&#xff0c;解压到当前文件夹&#xff0c;使用过程中别打开防火墙、杀毒软件。打开软件后&#xff0c;…

移动WEB开发五、响应式布局

零、文章目录 文章地址 个人博客-CSDN地址&#xff1a;https://blog.csdn.net/liyou123456789个人博客-GiteePages&#xff1a;https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee&#xff1a;https://gitee.com/bluecusliyou/TechLearnGithub&#xff1a;https:…

SAP FICO 理解业务范围的概念

业务范围 以前转载过几篇关于业务范围的文章&#xff1a; SAP Business Area 业务范围_SAP剑客的博客-CSDN博客_sap 业务范围 SAP FI 系列 002&#xff1a;业务范围派生_stone0823的博客-CSDN博客_sap 业务范围 http://blog.sina.com.cn/s/blog_3f2c03e30102w9yz.html 仍是…

虹科新品 | 最高80W!用于大基板紫外曝光系统的高功率UVLED光源

光刻曝光是指利用紫外光源将胶片或其他透明物体上的图像信息转移到涂有光敏材料&#xff08;光刻胶&#xff09;表面以得到高精度和极细微图案的一种制作工艺&#xff0c;主要用于半导体生产、高精密集成电路、PCB板制造、MEMS等行业。光刻技术是半导体工业和集成电路是最为核心…

十一、项目实战一

项目实战一 需求 以 前后端不分离的方式实现学生的增删改查操作 学生列表功能 接口设计 url:/students/ 请求方法&#xff1a;get 参数&#xff1a; 格式&#xff1a;查询参数 参数名类型是否必传说明pageint否页码&#xff0c;默认为1sizeinit否每页数据条数默认为10n…

浅谈安科瑞电力智能运维在高速铁路电力系统的应用分析

摘 要&#xff1a;高速铁路电力智能运维管理系统采用终端感知层、系统网络层、系统平台层的三层网络架构模式&#xff0c;通过集成网关&#xff0c;共享通信传输设备&#xff0c;利用铁路专用运维传输网络通道将各类监测数据上传至运维管理平台数据进行实时分析&#xff0c;建…

k8s二进制部署

目录 一、K8S常见的部署方式 1.1 K8S常见的部署方式 1.2 k8s部署 二进制与高可用的区别 二、Kubernetes二进制部署 2.1 Kubernetes二进制部署准备 ① 服务器准备 ② 签发证书环境准备 2.2 操作系统初始化配置 2.3 部署 etcd 集群 ① 在 master01 节点上操作 ② work…

使用Fabric.js实现贝塞尔曲线波浪特效

一、前言 本文是在此基础上收到启发然后进行的变化&#xff0c;当然&#xff0c;观看与否不会影响接下来的阅读体验。 二、实现思路 其实整个波浪动画其实可以看成&#xff1a;在相对坐标系静止的视角下&#xff0c;一个正弦函数在直角坐标系上匀速平移时我们所观察到的效果…

如何防止订单重复提交

如何防止订单重复提交前言什么是重复下单为什么会重复下单&#xff1f;如何处理重复下单&#xff1f;利用数据库实现幂等利用Redis防重前言 最近在做电商项目&#xff0c;整理一下解决方案并帮助自己巩固知识点&#xff0c;此方案是结合了目前的业务环境&#xff0c;若有更好的…

Linux进程概念讲解

1、进程的基本概念在给进程下定义之前&#xff0c;我们先了解一下进程&#xff1a;我们在编写完代码并运行起来时&#xff0c;在我们的磁盘中会形成一个可执行文件&#xff0c;当我们双击这个可执行文件时&#xff08;程序时&#xff09;&#xff0c;这个程序会加载到内存中&am…

中央计算平台「上车」加速

随着英伟达、高通宣布在2024年开始陆续交付中央计算平台&#xff0c;Tier1正在跨域联合&#xff0c;以寻求在新的行业周期获得先发优势。 本月初&#xff0c;韩国LG电子宣布与高通达成合作协议&#xff0c;在原有座舱计算平台基础上&#xff0c;进一步拓展至智能驾驶领域。而在…

Transformer架构理解

参考&#xff1a; 1. Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Łukasz Kaiser, and Illia Polosukhin. 2017. Attention is all you need. In Proceedings of the 31st International Conference on Neural Information Pr…

Java 语法糖详解

本文从 Java 编译原理角度&#xff0c;深入字节码及 class 文件&#xff0c;抽丝剥茧&#xff0c;了解 Java 中的语法糖原理及用法&#xff0c;帮助大家在学会如何使用 Java 语法糖的同时&#xff0c;了解这些语法糖背后的原理。 什么是语法糖&#xff1f; 语法糖&#xff08…