当前位置: 首页 > news >正文

AI刷题-多零件流水线优化问题

目录

问题描述

测试样例

 解题思路:

问题理解

数据结构选择

算法步骤

代码实现: 

1.创建数组标记每个零件的每个工序是否完成。 

2.创建数组存储每个零件的工序数量。

3.创建数组存储每个零件的工序时间。 

 4.初始化

5.设置下标 

6.创建优先队列 

 7.模拟整个零件加工

最终代码: 

运行结果: 


问题描述

小C、小U、小R是工厂里的三个工人,他们互相协同制作零件。零件的制作包括三种工序:"加工"、"质检"、"收尾",分别由小C、小U、小R负责。每个零件需要多次进行"加工"和"质检"工序,但只需要进行一次"收尾"工序。每次"加工"完成后,需要进行对应的"质检",只有当质检合格后,才可以开始下一次"加工"。当所有的"加工"和"质检"工序完成后,进行一次"收尾"工序,这样零件制作就算完成了。

小C、小U、小R的工作方式原本非常机械化,他们只能按照既定顺序一个工序一个工序地完成一个零件,比如对于一个零件的工序"加工1、质检1、加工2、质检2、收尾",他们会按顺序逐一完成各自的任务。

老板觉得这样太低效了,于是制定了新的加工方式:小C、小U、小R之间不应该互相等待,当他们因工序等待而被阻塞时,可以直接开始新零件的加工。但是每个工序在进行中不能被打断,必须连贯地完成。

例如,有5个零件,每个零件有7道工序,分别耗时如下:

零件一:10, 10, 10, 10, 10, 10, 20
零件二:10, 10, 10, 10, 10, 10, 20
零件三:10, 10, 10, 10, 10, 10, 20
零件四:10, 10, 10, 10, 10, 10, 20
零件五:10, 10, 10, 10, 10, 10, 20

(每一行的7个数字分别表示"加工1","质检1","加工2","质检2","加工3","质检3","收尾"的耗时)

假设零件按照5、4、3、2、1的优先级开始制作,优化后的工序流程中,小C、小U、小R会更加忙碌,避免空闲。

现在给你n个零件及每个零件的工序耗时,问在经过流程优化后,所有零件加工需要花费的总时间是多少?


测试样例

样例1:

输入:n = 5, parts = [[7, 10, 10, 10, 10, 10, 10, 20], [7, 10, 10, 10, 10, 10, 10, 20], [7, 10, 10, 10, 10, 10, 10, 20], [7, 10, 10, 10, 10, 10, 10, 20], [7, 10, 10, 10, 10, 10, 10, 20]]
输出:200

样例2:

输入:n = 3, parts = [[5, 10, 5, 10, 5, 10], [5, 2, 4, 6, 2, 10], [3, 10, 2, 5]]
输出:57

样例3:

输入:n = 4, parts = [[5, 7, 5, 8, 5, 7], [3, 5, 2, 7], [5, 3, 6, 4, 3, 6], [7, 7, 3, 4, 7, 3, 5, 6]]
输出:60

 解题思路:

问题理解

我们需要计算所有零件加工完成所需的总时间。每个零件的加工流程包括多个"加工"和"质检"工序,最后有一个"收尾"工序。小C、小U、小R可以并行工作,但每个工序必须连贯完成,不能被打断。

数据结构选择

  1. 零件列表std::vector<std::vector<int>> parts,其中每个子向量表示一个零件的工序耗时。
  2. 时间记录:我们可以使用三个变量来记录小C、小U、小R的当前时间,分别表示他们完成当前工序的时间点。

算法步骤

  1. 初始化:初始化小C、小U、小R的当前时间为0。
  2. 遍历零件:按照优先级遍历每个零件。
  3. 处理每个零件的工序
    • 对于每个零件的每个工序(加工、质检、收尾),计算小C、小U、小R完成该工序的时间。
    • 更新小C、小U、小R的当前时间,确保他们不会互相等待。
  4. 计算总时间:所有零件加工完成后,总时间即为小C、小U、小R中最后一个完成的时间。

代码实现: 

1.创建数组标记每个零件的每个工序是否完成。 

 

vector<vector<int>> flag(n, vector<int>(parts[0].size(), 0));

2.创建数组存储每个零件的工序数量。

vector<int> b(n);

3.创建数组存储每个零件的工序时间。 

vector<vector<int>> a(n);

 4.初始化

将parts里面的每一个工序的第一个零件放进对应的b数组里面,同时将第一个零件的时间都累加(已经加工了),然后把每一行的第二个到最后一个零件都放进a数组,最后标记flag数组的第一列的零件都为加工完成 

	for (int i = 0; i < n; ++i) {
		b[i] = parts[i][0];
		sum_jobs += b[i];
		a[i] = vector<int>(parts[i].begin() + 1, parts[i].end());
		flag[i][0] = 1;
	}

5.设置下标 

  1. time: 表示当前的时间点。
  2. m1m2m3: 分别表示当前加工、质检和收尾工序的结束时间。
  3. last1ilast1j: 记录上一次加工工序的零件索引和工序索引。
  4. last2ilast2j: 记录上一次质检工序的零件索引和工序索引。
  5. last3i: 记录上一次收尾工序的零件索引。

 

	int time = 0;
	int m1 = 0, m2 = 0, m3 = 0;
	int last1i = -1, last1j = -1;
	int last2i = -1, last2j = -1;
	int last3i = -1;

6.创建优先队列 

priority_queue<int, vector<int>, greater<int>> q;
	q.push(0);

 7.模拟整个零件加工

对于外循环:

  • q.top() 获取优先队列 q 中的最小时间值(因为 q 是一个最小堆)。
  • q.pop() 移除这个最小时间值。

内循环:

  • q.top() == time 检查队列顶部的下一个任务是否与当前时间 time 相同。
  • q.pop() 移除这个任务。

 

	while (sum_jobs > 0) {
		time = q.top();
		q.pop();
		
		while (!q.empty() && q.top() == time) {
			q.pop();
		}
		
		if (time == m3 && last3i != -1) {
			sum_jobs -= 1;
		}
		
		if (time == m2 && last2i != -1 && last2j != -1) {
			flag[last2i][last2j + 1] = 1;
			sum_jobs -= 1;
		}
		
		if (time >= m1) {
			if (time == m1 && last1i != -1 && last1j != -1) {
				flag[last1i][last1j + 1] = 1;
				sum_jobs -= 1;
			}
			
			// Get suitable m1
			bool found = false;
			for (int i = 0; i < n; ++i) {
				for (int j = 0; j < b[i]; j += 2) {
					if (flag[i][j] == 1 && j != b[i] - 1) {
						int temi = i, temj = j;
						flag[temi][temj] = 0;
						m1 = time + a[temi][temj];
						last1i = temi;
						last1j = temj;
						q.push(m1);
						found = true;
						break;
					}
				}
				if (found) break;
			}
		}
		
		if (time >= m2) {
			// Get suitable m2
			bool found = false;
			for (int i = 0; i < n; ++i) {
				for (int j = 1; j < b[i]; j += 2) {
					if (flag[i][j] == 1) {
						int temi = i, temj = j;
						flag[temi][temj] = 0;
						m2 = time + a[temi][temj];
						last2i = temi;
						last2j = temj;
						q.push(m2);
						found = true;
						break;
					}
				}
				if (found) break;
			}
		}
		
		if (time >= m3) {
			// Get suitable m3
			for (int i = 0; i < n; ++i) {
				if (flag[i][b[i] - 1] == 1) {
					int temi = i;
					flag[temi][b[temi] - 1] = 0;
					m3 = time + a[temi][b[temi] - 1];
					last3i = temi;
					q.push(m3);
					break;
				}
			}
		}
	}

 

 

 

 

 

 

最终代码: 

 

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

int solution(int n, vector<vector<int>> parts) {
	
	vector<vector<int>> flag(n, vector<int>(parts[0].size()+10, 0));//标记每个零件的每个工序是否完成
	vector<int> b(n,0);//保存每个零件的工序数量
	int sum_jobs = 0;
	vector<vector<int>> a(n);//存储每个零件的工序时间
	
	for (int i = 0; i < n; ++i) {
		b[i] = parts[i][0];
		sum_jobs += b[i];
		a[i] = vector<int>(parts[i].begin() + 1, parts[i].end());
		flag[i][0] = 1;
	}
	
	int time = 0;
	int m1 = 0, m2 = 0, m3 = 0;
	int last1i = -1, last1j = -1;
	int last2i = -1, last2j = -1;
	int last3i = -1;
	
	priority_queue<int, vector<int>, greater<int>> q;
	q.push(0);
	
	while (sum_jobs > 0) {
		time = q.top();
		q.pop();
		
		while (!q.empty() && q.top() == time) {
			q.pop();
		}
		
		if (time == m3 && last3i != -1) {
			sum_jobs -= 1;
		}
		
		if (time == m2 && last2i != -1 && last2j != -1) {
			flag[last2i][last2j + 1] = 1;
			sum_jobs -= 1;
		}
		
		if (time >= m1) {
			if (time == m1 && last1i != -1 && last1j != -1) {
				flag[last1i][last1j + 1] = 1;
				sum_jobs -= 1;
			}
			
			// Get suitable m1
			bool found = false;
			for (int i = 0; i < n; ++i) {
				for (int j = 0; j < b[i]; j += 2) {
					if (flag[i][j] == 1 && j != b[i] - 1) {
						int temi = i, temj = j;
						flag[temi][temj] = 0;
						m1 = time + a[temi][temj];
						last1i = temi;
						last1j = temj;
						q.push(m1);
						found = true;
						break;
					}
				}
				if (found) break;
			}
		}
		
		if (time >= m2) {
			// Get suitable m2
			bool found = false;
			for (int i = 0; i < n; ++i) {
				for (int j = 1; j < b[i]; j += 2) {
					if (flag[i][j] == 1) {
						int temi = i, temj = j;
						flag[temi][temj] = 0;
						m2 = time + a[temi][temj];
						last2i = temi;
						last2j = temj;
						q.push(m2);
						found = true;
						break;
					}
				}
				if (found) break;
			}
		}
		
		if (time >= m3) {
			// Get suitable m3
			for (int i = 0; i < n; ++i) {
				if (flag[i][b[i] - 1] == 1) {
					int temi = i;
					flag[temi][b[temi] - 1] = 0;
					m3 = time + a[temi][b[temi] - 1];
					last3i = temi;
					q.push(m3);
					break;
				}
			}
		}
	}
	
	return time;
}

int main() {
	vector<vector<int>> parts1 = {{7, 10, 10, 10, 10, 10, 10, 20},
		{7, 10, 10, 10, 10, 10, 10, 20},
		{7, 10, 10, 10, 10, 10, 10, 20},
		{7, 10, 10, 10, 10, 10, 10, 20},
		{7, 10, 10, 10, 10, 10, 10, 20}};
	vector<vector<int>> parts2 = {{5, 10, 5, 10, 5, 10},
		{5, 2, 4, 6, 2, 10},
		{3, 10, 2, 5}};
	vector<vector<int>> parts3 = {{5,7,5,8,5,7},{3,5,2,7},{5,3,6,4,3,6},{7,7,3,4,7,3,5,6}};
	cout << (solution(5, parts1) == 200) << endl;
	cout << (solution(3, parts2) == 57) << endl;
	cout << (solution(4, parts3) == 60) << endl;
	return 0;
}

 

运行结果: 

 

 

相关文章:

  • vue 判断一个属性值,如果是null或者空字符串或者是空格没有值的情况下,赋值为--
  • 【并发压测】高并发下Linux流量监控
  • TensorFlow 概念
  • 第五章 起航12 实习的小鸽飞了
  • 【RK3588嵌入式图形编程】-SDL2-构建模块化UI
  • istio介绍补充以及使用篇
  • 美团MTSQL特性解析:技术深度与应用广度的完美结合
  • Jmeter进阶篇(34)如何解决jmeter.save.saveservice.timestamp_format=ms报错?
  • 对学习编程语言的一些理解
  • Linux:文件(二)
  • flutter将utf-8编码的字节序列转换为中英文字符串
  • STL —— 洛谷字符串(string库)入门题(蓝桥杯题目训练)(二)
  • FreeRTOS学习笔记
  • Ubuntu 的RabbitMQ安装
  • Spring Boot项目中解决跨域问题(四种方式)
  • 使用WebStorm开发Vue3项目
  • AI大模型有哪些常见的应用场景
  • MySQL如何解决幻读?
  • 【git-hub项目:YOLOs-CPP】本地实现05:项目移植
  • 接口测试基础 --- 什么是接口测试及其测试流程?
  • 蒲慕明院士:未来数十年不是AI取代人,而是会用AI的人取代不会用的
  • 国际金价下跌,中概股多数上涨,穆迪下调美国主权信用评级
  • 苏轼“胡为适南海”?
  • 爱德华多·阿拉纳宣誓就任秘鲁新总理
  • 内塔尼亚胡:以军将在未来几天“全力进入”加沙
  • 国务院关税税则委员会关于调整对原产于美国的进口商品加征关税措施的公告