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

目录

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 ;
}

  • 21
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值