P1065 [NOIP2006 提高组] 作业调度方案题目

题目

我们现在要利用m台机器加工n个工件,每个工件都有m道工序,每道工序都在不同的指定的机器上完成。每个工件的每道工序都有指定的加工时间。

每个工件的每个工序称为一个操作,我们用记号j-k表示一个操作,其中j为1到n中的某个数字,为工件号;k为1到m中的某个数字,为工序号,例如2-4表示第2个工件第4道工序的这个操作。在本题中,我们还给定对于各操作的一个安排顺序。

例如,当n=3,m=2时,1-1,1-2,2-1,3-1,3-2,2-2就是一个给定的安排顺序,即先安排第1个工件的第1个工序,再安排第1个工件的第2个工序,然后再安排第2个工件的第1个工序,等等。

一方面,每个操作的安排都要满足以下的两个约束条件。

  1. 对同一个工件,每道工序必须在它前面的工序完成后才能开始;

  2. 同一时刻每一台机器至多只能加工一个工件。

另一方面,在安排后面的操作时,不能改动前面已安排的操作的工作状态。

由于同一工件都是按工序的顺序安排的,因此,只按原顺序给出工件号,仍可得到同样的安排顺序,于是,在输入数据中,我们将这个安排顺序简写为1 1 2 3 3 2

还要注意,“安排顺序”只要求按照给定的顺序安排每个操作。不一定是各机器上的实际操作顺序。在具体实施时,有可能排在后面的某个操作比前面的某个操作先完成。

例如,取n=3,m=2,已知数据如下(机器号/加工时间):

工件号工序 1工序 2
11/32/2
21/22/5
32/21/4

则对于安排顺序1 1 2 3 3 2,下图中的两个实施方案都是正确的。但所需要的总时间分别是10与12。

方案1,用时10:

时间12345678910
机器1执行工序1-11-11-12-12-13-23-23-23-2
机器2执行工序3-13-11-21-22-22-22-22-22-2

方案2,用时12:

时间123456789101112
机器1执行工序1-11-11-12-12-13-23-23-23-2
机器2执行工序1-21-23-13-12-22-22-22-22-2

当一个操作插入到某台机器的某个空档时(机器上最后的尚未安排操作的部分也可以看作一个空档),可以靠前插入,也可以靠后或居中插入。为了使问题简单一些,我们约定:在保证约束条件(1.)(2.) 的条件下,尽量靠前插入。并且,我们还约定,如果有多个空档可以插入,就在保证约束条件(1.)(2.)的条件下,插入到最前面的一个空档。于是,在这些约定下,上例中的方案一是正确的,而方案二是不正确的。

显然,在这些约定下,对于给定的安排顺序,符合该安排顺序的实施方案是唯一的,请你计算出该方案完成全部任务所需的总时间。

输入输出格式

输入格式

第1行为两个正整数m, n,用一个空格隔开, 其中m(<20) 表示机器数,n(<20)表示工件数。

第2行:m×n个用空格隔开的数,为给定的安排顺序。

接下来的2n行,每行都是用空格隔开的m个正整数,每个数不超过20。

其中前n行依次表示每个工件的每个工序所使用的机器号,第1个数为第1个工序的机器号,第2个数为第2个工序机器号,等等。

后n行依次表示每个工件的每个工序的加工时间。

可以保证,以上各数据都是正确的,不必检验。

输出格式

1 个正整数,为最少的加工时间。

输入输出样例

输入样例

2 3
1 1 2 3 3 2
1 2 
1 2 
2 1
3 2 
2 5 
2 4

输出样例

10

解析

题目已经给出了安排好的工序,而每个工序需要在几号机上完成以及每个工序的时间也给了出来,我们要做的就是合理安排机器的工作,让总的加工时间最短。

按照题意的约定,最短方案有且只有一种,而且不必判断输入的合法性。

我们可以把机器想成若干个「时间线」,在这条时间线上去安排工作。

那么明显的,每个时间段对应的机器就只有俩状态:1.我在干活     2.我闲着呢

而每一个工件也有自己的加工要求,对于每个工件的工序,总应该先完成小号工序再完成大号工序,也就是必须顺着编号来。

每台机器只能在某时刻进行一种工作,并且后面的安排不能把前面的安排改动掉。

模拟的思想便是从左到右无限扫描整个时间线,然后去尝试插空。

有三个辅助数组,第一个是cnt_now_work_step,它表示当前取到工件的工序数。根据之前输入的workline,每个数都代表一个安排的工序,这个数组就是用来方便后面处理工序的。第二个是lasttime,它代表某个工件出现的最晚的时间(点),它可以用来方便我们扫描时间线,因为每一个工件必须要完全完成上一道工序后才能接着继续下一道工序。第三个是二维bool数组timeline,它代表某一台机器在某一个时间(点)上是不是正在干活。

有了这三个辅助数组,我们就可以开始按照模拟的思路写代码了。

我们取当前工件nowitem[i],让cnt_now_work_step[nowitem]++,即代表这个工件的工序+1,用nownumber记录当前工件在当前工序时位于哪一台机器,costtime表示做完这道工序应该花费的时间,lasttime[nowitem]+1便是我们扫描时间线的开端,注意lasttime记录的是时间点。这个for没有终止条件,因为时间轴可能会无穷远。

接下来是关键,判断从这个时间点到干完这道工序,机器有没有空,如果机器表示“我闲着呢”,那么就把这道工序安排给机器的这个时间段,更新timeline和lasttime(lasttime[nowitem] = time + costtime - 1,干完活之后这个工件出现的最晚的时间点应该是这道新工序做完的那一刻),然后更新操作立即break掉,继续扫描时间线。如果机器表示“这个时间段我在干其他活”,那这个任务就不能放在这一段,时间线继续扫描。

这个判断这里用一个函数来实现,它传入起始时间点和终止时间点和工件编号,然后去判断它的timeline。循环完所有的工件,整个的时间轴也就确定了。最后去寻找ans,ans应该等于值最大的那个lasttime(即这个工件最后才做完)。输出ans即可。

代码

#include<iostream>
#define maxn 100
using namespace std;
int n,m;//定义工件数和机器数 
int ans = 0;//最后输出的结果 
int worklist[maxn * maxn];
int worknumber[maxn][maxn];
int worktime[maxn][maxn];
int cnt_now_work_step[maxn];
int lasttime[maxn];
bool timeline[maxn * maxn][maxn * maxn];//某一台机器在某一个时间(点)上是不是正在干活bool check_in_line(int begin_time_point,int end_time_length,int workid){for (int time = begin_time_point; time <= end_time_length;time++)if (timeline[workid][time])return false;return true;    
}//判断机器是不是空闲 int main(){cin >> m >> n;//输入机器数和工件数 for (int i=1;i<=n*m;i++){ cin >> worklist[i];//输入给定的安排顺序 } for (int i=1;i<=n;i++){ for (int j=1;j<=m;j++){ cin >> worknumber[i][j];//每一工件每个工序的机器号 }} for (int i=1;i<=n;i++){ for (int j=1;j<=m;j++){ cin >> worktime[i][j];//每个工件每个工序的加工时间 }} for (int i=1;i<=n*m;i++){int nowitem = worklist[i];//工件的安排顺序 cnt_now_work_step[nowitem]++;//当前取到工件的工序数int nownumber = worknumber[nowitem][cnt_now_work_step[nowitem]];//当前工件在当前工序时位于哪一台机器 int costtime = worktime[nowitem][cnt_now_work_step[nowitem]];//当前工件做完当前工序的加工时间 for (int time = lasttime[nowitem]+1;;time++)//扫描时间轴if (check_in_line(time,time+costtime-1,nownumber)){for (int marktime = time;marktime <= time+costtime-1;marktime++)timeline[nownumber][marktime] = true;lasttime[nowitem] = time + costtime - 1;break;}}for (int i=1;i<=n;i++)ans = max(ans,lasttime[i]);cout << ans << endl;return 0;
}

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

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

相关文章

群辉NAS的远程访问

群辉NAS是私有云存储&#xff0c;局域网访问很容易【详见&#xff1a;网上邻居访问设置、其它设备的访问设置】&#xff0c;远程访问相对复杂&#xff0c;涉及很多关键因素&#xff0c;现将过程记录如下&#xff1a; 目录 1、互联网接入 2、绑定MAC与IP地址 3、路由器开启5…

算法随想录第四十三天打卡|1049. 最后一块石头的重量 II ,494. 目标和 ,474.一和零

1049. 最后一块石头的重量 II 本题就和 昨天的 416. 分割等和子集 很像了&#xff0c;可以尝试先自己思考做一做。 视频讲解&#xff1a;动态规划之背包问题&#xff0c;这个背包最多能装多少&#xff1f;LeetCode&#xff1a;1049.最后一块石头的重量II_哔哩哔哩_bilibili 代…

eclipse中导入运行MyEclipse项目...非常实用

eclipse中导入运行MyEclipse项目 进入项目目录&#xff0c;找到.project文件&#xff0c;打开找到<natures>...</natures>代码段。在第2步的代码段中加入如下标签内容并保存&#xff1a; <nature>org.eclipse.wst.common.project.facet.core.nature</na…

mysql中获取一段时间日期

SELECTdate_add(date_sub(20230201, interval 1 day), INTERVAL (cast(help_topic_id AS signed INTEGER) 1) day) as tttt FROM mysql.help_topic WHERE help_topic_id < DATEDIFF(20230201, date_sub(20230101, interval 1 day)) ORDER BY help_topic_id其中mysql.help_t…

SpringMVC-HttpMessageConverter 报文信息转化器

文章目录 HttpMessageConverter一、概念二、RequestBody三、RequestEntity四、 ResponseBody1.返回JSON格式的字符串 五、RestController六、ResponseEntity HttpMessageConverter 一、概念 报文信息转化器&#xff0c;将请求报文转化为Java对象&#xff0c;或将Java对象转化…

Java笔记(死锁、线程通信、单例模式)

一、死锁 1.概述 死锁 : 死锁是指两个或两个以上的进程在执行过程中&#xff0c;由于竞争资源或者由于彼此通信而造成的一种阻塞的现象&#xff0c;若无外力作用&#xff0c;它们都将无法往下执行。此时称系统处于死锁状态或系统产生了死锁&#xff0c;这些永远在互相等待的进…

【Digester解析XML文件的三种方式】

Digester解析XML文件的三种方式 1. Digester解析XML文件的三种方式1.1 作用及依赖jar包 2. 重点和难点3. XML文件4. 通过不同的方式解析这个xml文件4.1 通过java编码方式解析&#xff08;javabean存储&#xff09;4.2 通过java编码方式解析&#xff08;list和map存储&#xff0…

【ChatGPT 和文心一言哪个更好用?】

ChatGPT 和文心一言哪个更好用&#xff1f; 随着人工智能技术的飞速发展&#xff0c;AI 助手已经成为人们日常生活和工作中不可或缺的一部分。在众多 AI 助手中&#xff0c;ChatGPT 和文心一言备受关注。本文将从智能回复、语言准确性、知识库丰富度等方面对这两大 AI 助手进行…

Leetcode 俩数之和(哈希)

一、题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以…

【LMDeploy 大模型量化部署实践】学习笔记

参考学习教程【LMDeploy 的量化和部署】 理论 作业 使用 LMDeploy 以本地对话、网页Gradio、API服务中的一种方式部署 InternLM-Chat-7B 模型&#xff0c;生成 300 字的小故事 本地对话 API服务 Client 命令 端口转发 网页Gradio

一文学习Thrift RPC

Thrift RPC引言 Thrift RPC的特点 Thrift 是一个RPC的框架&#xff0c;和Hessian RPC有什么区别&#xff0c;最重要的区别是Thrift可以做异构系统开发。 什么是异构系统&#xff0c;服务的提供者和服务的调用者是用不同语言开发的。 为什么会当前系统会有异构系统的调用&…

【WPF.NET开发】WPF 中的 Layout

本文内容 元素边界框布局系统测量和排列子元素面板元素和自定义布局行为布局性能注意事项子像素渲染和布局舍入 本主题介绍 Windows Presentation Foundation (WPF) 布局系统。 了解布局计算发生的方式和时间对于在 WPF 中创建用户界面非常重要。 1、元素边界框 在 WPF 中构…

Apollo Cyber RT:引领实时操作系统在自动驾驶领域的创新

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下…

深入理解旅游网站开发:Java+SpringBoot+Vue+MySQL的实战经验

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

ChatGPT 全域调教高手:成为人工智能交流专家

随着人工智能的快速发展&#xff0c;ChatGPT作为一种强大的文本生成模型&#xff0c;在各行各业中越来越受到重视和应用。想要利用ChatGPT实现更加智能、自然的交流&#xff0c;成为 ChatGPT 全域调教高手吗&#xff1f;本文将为您介绍如何通过优化ChatGPT的训练方法&#xff0…

jquery多选框

使用hbuilder <!DOCTYPE html> <html><head><meta charset"GBK"><title></title></head><body><table id"myTable"> <tr> <td>黄1</td> </tr> <tr> <td>…

JAVA泛型、泛型通配符、综合练习

作用&#xff1a; 是 jdk5 中引入的特性&#xff0c;可以在编译阶段 约束 操作的数据类型&#xff0c;并进行检查。 格式&#xff1a; <数据类型> 注意泛型只能支持引用数据类型&#xff0c;基本数据类型可转成对应的包装类。 问题&#xff1a; 在没有泛型的时候&…

Redis的RDB和AOF详解

Redis的RDB和AOF详解 欢迎来到本博客&#xff0c;今天我们将深入探讨Redis中的RDB&#xff08;Redis DataBase&#xff09;和AOF&#xff08;Append Only File&#xff09;两种持久化机制。这两种机制在Redis中负责将内存中的数据持久化到硬盘&#xff0c;保障数据的持久性和可…

前端demo: 将传入文件压缩到不超过指定大小(M)

1.compressImage函数&#xff1a;通过canvas将选择文件压缩后展示在页面上 2.compressImageToSetsize函数&#xff1a;传入参数file, quality 0.6,setsize 1&#xff0c;借助compressorjs将传入文件压缩到不超过指定大小&#xff08;M&#xff09; 3.compressImageN&#x…

UE使用C++添加FGameplayTag(游戏标签)

首先Ue会有一个UGameplayTagsManager类型的对象 游戏标签管理器(全局中就有一个) 我们直接通过 UGameplayTagsManager::Get()静态函数拿到 全局唯一的游戏标签管理器的实例 返回的是个左值引用 之后通过调用 AddNativeGameplayTag()函数就可添加游戏标签了 就这么简单 第…