L2-041 插松枝+L2-042 老板的作息表详解

本文介绍了如何根据工人在人造松枝加工场的工作流程编写程序,处理松针插入松枝干的过程,并解决老板作息表中未列出时间段的问题。通过分析工作规则,设计了相应的算法实现输出每根成品松枝的松针序列和未填写的时间段。
摘要由CSDN通过智能技术生成

目录

L2-041 插松枝

题目

题解

L2-042 老板的作息表

题目

题解

L2-041 插松枝

题目

人造松枝加工场的工人需要将各种尺寸的塑料松针插到松枝干上,做成大大小小的松枝。他们的工作流程(并不)是这样的:

  • 每人手边有一只小盒子,初始状态为空。
  • 每人面前有用不完的松枝干和一个推送器,每次推送一片随机型号的松针片。
  • 工人首先捡起一根空的松枝干,从小盒子里摸出最上面的一片松针 —— 如果小盒子是空的,就从推送器上取一片松针。将这片松针插到枝干的最下面。
  • 工人在插后面的松针时,需要保证,每一步插到一根非空松枝干上的松针片,不能比前一步插上的松针片大。如果小盒子中最上面的松针满足要求,就取之插好;否则去推送器上取一片。如果推送器上拿到的仍然不满足要求,就把拿到的这片堆放到小盒子里,继续去推送器上取下一片。注意这里假设小盒子里的松针片是按放入的顺序堆叠起来的,工人每次只能取出最上面(即最后放入)的一片。
  • 当下列三种情况之一发生时,工人会结束手里的松枝制作,开始做下一个:

(1)小盒子已经满了,但推送器上取到的松针仍然不满足要求。此时将手中的松枝放到成品篮里,推送器上取到的松针压回推送器,开始下一根松枝的制作。

(2)小盒子中最上面的松针不满足要求,但推送器上已经没有松针了。此时将手中的松枝放到成品篮里,开始下一根松枝的制作。

(3)手中的松枝干上已经插满了松针,将之放到成品篮里,开始下一根松枝的制作。

现在给定推送器上顺序传过来的 N 片松针的大小,以及小盒子和松枝的容量,请你编写程序自动列出每根成品松枝的信息。

输入格式:

输入在第一行中给出 3 个正整数:N(≤103),为推送器上松针片的数量;M(≤20)为小盒子能存放的松针片的最大数量;K(≤5)为一根松枝干上能插的松针片的最大数量。

随后一行给出 N 个不超过 100 的正整数,为推送器上顺序推出的松针片的大小。

输出格式:

每支松枝成品的信息占一行,顺序给出自底向上每片松针的大小。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

8 3 4
20 25 15 18 20 18 8 5

输出样例:

20 15
20 18 18 8
25 5

题解

分析一下:
【注:一定是先看小盒子有没有满足条件的松针,小盒子没有才轮的上传送器】 
取: 
1、先取小盒子(先取最后放入的)的,满足条件就一直取,反之,
(注:进行下面的2的前提:(同时满足) 
  (1)就是小盒子中最上面的松针不满足要求或者盒子空了
  (2)松枝干还没有插满,没插满才轮的上推送器
  ) 
 
2、看则推送器:
    2.1、 松针满足要求,就取之插好,一直从推送器取,盒子取不了 
    2.2、  不满足要求(也即是退出),有三个原因,也是退出原因
        2.2.1 小盒子已经满了,不满足的松针放盒子放不下了 
        2.2.2 推送器上已经没有松针了
        2.2.3 松枝干上已经插满了松针

退:工人会结束手里的松枝制作,开始做下一个
退1、    小盒子已经满了,但推送器上取到的松针仍然不满足要求 。
退2、 小盒子中最上面的松针不满足要求,但推送器上已经没有松针了。
退3、手中的松枝干上已经插满了松针,将之放到成品篮里,开始下一根松枝的制作。

更多的思路写在代码注释里面的,写的很清楚,大家可以仔细看看

/*
分析一下:
【注:一定是先看小盒子有没有满足条件的松针,小盒子没有才轮的上传送器】 
取: 
1、先取小盒子(先取最后放入的)的,满足条件就一直取,反之,
(注:进行下面的2的前提:(同时满足) 
  (1)就是小盒子中最上面的松针不满足要求或者盒子空了
  (2)松枝干还没有插满,没插满才轮的上推送器
  ) 
 
2、看则推送器:
	2.1、 松针满足要求,就取之插好,一直从推送器取,盒子取不了 
	2.2、  不满足要求(也即是退出),有三个原因,也是退出原因
		2.2.1 小盒子已经满了,不满足的松针放盒子放不下了 
		2.2.2 推送器上已经没有松针了
		2.2.3 松枝干上已经插满了松针

退:工人会结束手里的松枝制作,开始做下一个
退1、	小盒子已经满了,但推送器上取到的松针仍然不满足要求	
退2、 小盒子中最上面的松针不满足要求,但推送器上已经没有松针了。
退3、手中的松枝干上已经插满了松针,将之放到成品篮里,开始下一根松枝的制作。
*/ 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N= 5e5 + 24, inf = 1e9 + 7, M = 1e1+24;
stack<int> s; //来存小盒子里面的松针的,这个需要后进先出嘛,先取最后放入的
queue<int> q; // 存推送器传送的松针 ,先来先取 

int main() 
{
	int n, m, k, i, j, t;
	cin >> n >> m >> k;
	for(i = 0; i < n; i ++)
	{
		cin >> t;
		q.push(t); //松针入传送器  
	} 
	
	//开始把松针插到松枝干上 
	while(1)
	{
		vector<int> ve; // 定义松枝干 
		//1、先取小盒子(先取最后放入的)的,满足条件就一直取
		/* 
		原因:
		1.1 s小盒子非空,非空才能取嘛
		1.2  松枝干插的松针片要小于一根松枝干上能插的松针片的最大数量
		1.3  松枝干没有松枝直接插进去,或者满足“需要保证,每一步插到一根非空松枝干上的松针片,不能比前一步插上的松针片大” 
		*/
		while(!s.empty() && ve.size() < k && (ve.size() == 0 || s.top() <= ve[ve.size()-1]))
		{
			ve.push_back(s.top()); //插进去
			s.pop(); //取下来 
		}
		
		// 退3:手中的松枝干上已经插满了松针,将之放到成品篮里,开始下一根松枝的制作。
		if(ve.size() == k)
		{
			// 输出
			for(i = 0; i < ve.size(); i ++)
			{
				if(i)	cout << " ";
				cout << ve[i];
			} 
			cout << endl;
			// 开始下一轮,这里可能不太好理解continue
			/*
			因为这里退出的原因是松枝干满了,可能小盒子非空,
			我们始终要 先取小盒子里面的松枝 
			*/ 
			continue;
		}
		
		// 接下来是松枝干还没有装满,开始看推送器的,有没有满足条件的
		while(!q.empty() && ve.size() < k)
		{
			if(ve.size() == 0 || q.front() <= ve[ve.size()-1])
			{
				ve.push_back(q.front()); //插进去
				q.pop(); //取下来 
			}
			// q.front() > ve[ve.size()-1] 
	 		else 
	 		{
	 			// 小盒子能装下 
	 			if(s.size() < m)
				{
				 	s.push(q.front()); //插进小盒子 
					q.pop(); //取下来 
				} 
				//. 退1:小盒子已经满了,但推送器上取到的松针仍然不满足要求。 
				else
				{
					break;
				} 
			}
		}
		// 退出整个过程,松针插完了 ,不然ve不可能为空 
		if(ve.size() == 0)  break;
		
		// 下面输出:原因:退1-退3三个原因都可能,就是不满足上面while里面的条件
		for(i = 0; i < ve.size(); i ++)
		{
			if(i)	cout << " ";
			cout << ve[i];
		} 
		cout << endl;
	} 
	return 0; 
} 

L2-042 老板的作息表

题目

新浪微博上有人发了某老板的作息时间表,表示其每天 4:30 就起床了。但立刻有眼尖的网友问:这时间表不完整啊,早上九点到下午一点干啥了?

本题就请你编写程序,检查任意一张时间表,找出其中没写出来的时间段。

输入格式:

输入第一行给出一个正整数 N,为作息表上列出的时间段的个数。随后 N 行,每行给出一个时间段,格式为:

hh:mm:ss - hh:mm:ss

其中 hhmmss 分别是两位数表示的小时、分钟、秒。第一个时间是开始时间,第二个是结束时间。题目保证所有时间都在一天之内(即从 00:00:00 到 23:59:59);每个区间间隔至少 1 秒;并且任意两个给出的时间区间最多只在一个端点有重合,没有区间重叠的情况。

输出格式:

按照时间顺序列出时间表中没有出现的区间,每个区间占一行,格式与输入相同。题目保证至少存在一个区间需要输出。

输入样例:

8
13:00:00 - 18:00:00
00:00:00 - 01:00:05
08:00:00 - 09:00:00
07:10:59 - 08:00:00
01:00:05 - 04:30:00
06:30:00 - 07:10:58
05:30:00 - 06:30:00
18:00:00 - 19:00:00

输出样例:

04:30:00 - 05:30:00
07:10:58 - 07:10:59
09:00:00 - 13:00:00
19:00:00 - 23:59:59

题解

这道题,我只想发出数学老师的感叹:完全就是送分题!!!知识要注意细节,00:00:00和23:59:59这两个边界值,排下序,看看这个数的开始时间是否是前一个数的结束时间即可,可以用结构体排序、优先队列、vector,我写了两个,思路是差不多的,一个是今年写的,一个是去年备赛的时候写的

// 用结构体排序 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N= 5e5 + 24, inf = 1e9 + 7, M = 1e1+24;

struct point{
	string begin;
	string end;
}p[N]; 

bool cmp(point x, point y)
{
//	if(x.begin == y.begin)	return x.end < y.end;
	return x.begin < y.begin;
}
int main() 
{
	int n, i, j;
	string s;
	cin >> n;
	for(i = 0; i < n; i ++)
	{
		cin >> p[i].begin >> s >> p[i].end;
	}
	sort(p, p+n, cmp);
	
	s = "00:00:00";
	for(i = 0; i < n; i ++)
	{
		if(p[i].begin != s)		cout << s << " - " << p[i].begin << endl;
		s = p[i].end;
	}
	if(s != "23:59:59")	cout << s << " - 23:59:59";
	
	return 0; 
} 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll ; 
const int N = 5e3+5 , M = 1e3+24 ;
vector< pair<string,string> > v ;
pair<string,string> temp ;
int main()
{
	int n , i , j ;
	string a , b , c , s ;
	cin >> n ;
	for(i = 0 ; i < n ; i ++)
	{
		cin >> temp.first >> s >> temp.second ;
		v.push_back(temp) ;
	}
//	for(i = 0 ; i < v.size() ; i ++)
//	{
//		cout << v[i].first << " " << v[i].second  << endl ;
//	}
	sort(v.begin() , v.end()) ;
//	for(i = 0 ; i < v.size() ; i ++)
//	{
//		cout << v[i].first << " " << v[i].second  << endl ;
//	}
	string last = "-1" ;
	for(i = 0 ; i < v.size() ; i ++)
	{
		temp = v[i] ;
		if(last == "-1")
		{
			if(temp.first != "00:00:00")
			{
				cout << "00:00:00 - " << temp.first << endl ;
//				printf("00:00:00 - %s\n" , temp.fisrt) ;
				
			}
			last = temp.second ;
		}
		else
		{
			if(last != temp.first)
			{
				cout << last << " - " << temp.first << endl ;
				
			}
			last = temp.second ;
		}
	}
	if(last != "23:59:59")  cout << last << " - 23:59:59" ;
	return 0 ;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值