Week 10 限时训练 B - 团 队 聚 会

题目描述

TA团队每周都会有很多任务,有的可以单独完成,有的则需要所有人聚到一起,开过会之后才能去做。但TA团队的每个成员都有各自的事情,找到所有人都有空的时间段并不是一件容易的事情。

给出每位助教的各项事情的时间表,你的任务是找出所有可以用来开会的时间段。

输入格式

第一行一个数T(T≤100),表示数据组数。

对于每组数据,第一行一个数m(2 ≤ m ≤ 20),表示TA的数量。

对于每位TA,首先是一个数n(0≤ n≤100),表示该TA的任务数。接下来n行,表示各个任务的信息,格式如下

YYYY MM DD hh mm ss YYYY MM DD hh mm ss “some string here”

每一行描述的信息为:开始时间的年、月、日、时、分、秒;结束时间的年、月、日、时、分、秒,以及一些字符串,描述任务的信息。

数据约定:

所有的数据信息均为固定位数,位数不足的在在前面补前导0,数据之间由空格隔开。

描述信息的字符串中间可能包含空格,且总长度不超过100。

所有的日期时间均在1800年1月1日00:00:00到2200年1月1日00:00:00之间。

为了简化问题,我们假定所有的月份(甚至2月)均是30天的,数据保证不含有不合法的日期。

注意每件事务的结束时间点也即是该成员可以开始参与开会的时间点。

输出格式

对于每一组数据,首先输出一行"Scenario #i:",i即表明是第i组数据。

接下来对于所有可以用来开会的时间段,每一个时间段输出一行。

需要满足如下规则:

  • 在该时间段的任何时间点,都应该有至少两人在场。
  • 在该时间段的任何时间点,至多有一位成员缺席。
  • 该时间段的时间长度至少应该1h。

所有的成员都乐意一天24h进行工作。

举个例子,假如现在TA团队有3位成员,TT、zjm、hrz。

那么这样的时间段是合法的:会议开始之初只有TT和zjm,后来hrz加入了,hrz加入之后TT离开了,此后直到会议结束,hrz和zjm一直在场。

要求:

  • 输出满足条件的所有的时间段,尽管某一段可能有400年那么长。
  • 时间点的格式为MM/DD/YYYY hh:mm:ss。
  • 时间段的输出格式为"appointment possible from T0 to T1",其中T0和T1均应满足时间点的格式。
  • 严格按照格式进行匹配,如果长度不够则在前面补前导0。
  • 按时间的先后顺序输出各个时间段。
  • 如果没有合适的时间段,输出一行"no appointment possible"。
  • 每组数据末尾须打印额外的一行空行。

一些感受

这题我想到了思路,但是没能在规定的时间内写完。很多同学也没能把这道题按时完成,可见其难度是很大的。
不过,这个题数据规模较小,从算法的角度来说难度并不大,使用近乎穷举的方式就可以解决。
我认为,它难在了以下的几个方面。

  1. 题干很长,理解起来比较费时间,而且容易看起来很难。
  2. 输入复杂,且包含冗余信息。输入中用年月日时分秒来表示信息,而这样并不方便计算和比较;另外,描述任务信息的字符串对于解决本题是不必要的。
  3. 输出复杂,必须把时间转成MM/DD/YYYY hh:mm:ss的格式。

以后还是应该多练习类似的模拟题,锻炼题目快速分析的能力。

基本思路

时间格式的互换

为了更加方便的对时间点进行运算和比较,我们可以将其转换成时间戳的形式(可以以1800年1月1日00:00:00为起始时间),转换方式即找到每一项(年月日时分秒)与1800,1,1,0,0,0的差值,然后转化成秒并求和。

另外,我们还需要将时间点转化成输出所需的格式。过程与上面的转换相反,将时间戳转化成年月日时分秒,然后在1800,1,1,0,0,0的基础上加上这些值,从而得到时间戳对应的年月日时分秒,然后按规定格式输出即可。

解题思路

输入中可以获取所有人的所有任务涉及的时间段,我们可以用一个二维数组se来记录(第一维度记录不同的人,第二维度记录时间段)。

然后,我们可以使用所有这些任务时间段涉及的时间点将1800年1月1日00:00:00到2200年1月1日00:00:00这段时间分成若干小段。可以发现,每一小段时间要么包含在某个任务时间内,要么和这个任务时间没有交集。包含这个时间段的任务对应的人是无法在这段时间去开会的。

于是我们可以遍历所有这样的小段时间,可以统计每一小段时间缺席和可以开会的人数,从而找到合法(至少两人在场,最多一人缺席)的时间段。如果最长连续合法时间段长度大于1h,那么这段时间就满足了条件,可以将其输出。

需要注意的点

  1. 月和日的最小值均是1,而不是0。
  2. 本题中每个月都是30天。
  3. 时间戳可能会很大,为了防止溢出,应该使用long long而不是int。
  4. 任务时间段涉及的时间点可能会有重复。

完整代码

#include<iostream>
#include<set>
#include<iomanip>
#include<algorithm>
#define maxTS  12441600000 
using namespace std;
struct Section{   //区间结构体 
	long long bg;
	long long ed;
	
	Section(long long b=0, long long e=0)
	{
		bg = b;
		ed = e;
	}
	
	bool contain(const Section &se)    
	{
		return bg <= se.bg && ed >= se.ed;
	}
	
	bool operator <(const Section &se) const
	{
		if(bg != se.bg)	return bg < se.bg;
		return ed < se.ed;
	}
	
}se[25][150];

set<long long> S;
long long t[10000], tc;    
int T, m, n[25];
int tsfm[6]={60,60,24,30,12};
long long timeStamp()   
{
	long long y, m, d, h, mi, s;
	cin>>y>>m>>d>>h>>mi>>s;
	return (((((y-1800)*12+(m-1))*30+(d-1))*24+h)*60+mi)*60+s;
}

void optT(long long t0)
{
	int t1[6];
	// 0  1  2  3  4  5
	// s  mi h  d  m  y
	for(int i=0;i<5;i++)
	{
		t1[i] = t0 % tsfm[i];
		t0 /= tsfm[i];
	}
	t1[5]=t0;
	cout<<setw(2)<<setfill('0')<<t1[4]+1<<"/";
	cout<<setw(2)<<setfill('0')<<t1[3]+1<<"/";
	cout<<setw(4)<<setfill('0')<<t1[5]+1800<<" ";
	cout<<setw(2)<<setfill('0')<<t1[2]<<":";
	cout<<setw(2)<<setfill('0')<<t1[1]<<":";
	cout<<setw(2)<<setfill('0')<<t1[0];
}

bool check(const Section &ts)
{
	int cnt = 0;
	for(int i=0;i<m;i++)
	{
		bool absent = false;
		for(int j=0;j<n[i];j++)
		{
			if(se[i][j].contain(ts))
			{
				absent=true;
				break;
			}
		}
		cnt += absent;
	}
	if(cnt <= 1 && (m-cnt) >= 2)	return true;
	return false;
} 

bool meetT(int &i)
{
	Section ts(-1,0);
	
	for(;i<tc-1 && check(Section(t[i], t[i+1]));i++)
	{
		if(ts.bg == -1)	ts.bg=t[i];
		ts.ed = t[i+1];	
	}
	
	if(ts.ed - ts.bg >= 3600)
	{
		cout<<"appointment possible from ";
		optT(ts.bg);
		cout<<" to ";
		optT(ts.ed);
		cout<<endl;
		return true;
	}
	return false;
}

int main ()
{
	ios::sync_with_stdio(false);
	cin>>T;
	for(int k=1;k<=T;k++)
	{
		{
			S.clear();
			tc=0;
			S.insert(0);
			t[tc++]=0;
		}
		cin>>m;
		char info[105];   //存储无用信息 
		for(int i=0;i<m;i++)
		{
			cin>>n[i];
			for(int j=0;j<n[i];j++)
			{
				se[i][j].bg = timeStamp();
				se[i][j].ed = timeStamp();
				if(S.find(se[i][j].bg) == S.end())
				{
					t[tc++] = se[i][j].bg;
					S.insert(se[i][j].bg);
				}
				if(S.find(se[i][j].ed) == S.end())
				{
					t[tc++] = se[i][j].ed;
					S.insert(se[i][j].ed); 
				}	
				cin.getline(info, 100);
			}
		}
		sort(t, t+tc);
		if(S.find(maxTS) ==S.end())	t[tc++] = maxTS;
		int i=0;
		bool flag=false;
		cout<<"Scenario #"<<k<<":"<<endl;
		for(int i=0;i<tc-1;i++)	flag = meetT(i) || flag;
		if (!flag)	cout<<"no appointment possible"<<endl;
		cout<<endl;
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在第4周的可重复研究项目中,我将继续探索如何使用开放源代码工具和技术来实现可重复性和透明度。 首先,我将继续使用版本控制系统(如Git),以便跟踪我研究项目中的所有更改和改进。这将确保我能够回溯到每个版本的数据和代码,并对项目进行可重复性验证。在本周内,我还将学习更多关于Git分支和合并的知识,以便更好地组织和管理我的项目。 另外,我还将使用Jupyter Notebook来记录我的实验过程和结果。Jupyter Notebook提供了一个互动环境,可以将代码、文档和图形化结果结合在一起,使得我的研究成果更加易于理解和重现。我确保我的Notebook中包含了所有必要的步骤和解释,以便他人能够准确地复现我的研究。 为了进一步提高可重复性,我还将采取一些数据预处理和清洗的措施。这些措施包括去除异常值、处理缺失数据和标准化数据等。我将确保我的数据处理过程明确记录,并提供相应的代码和文档,以便他人能够按照相同的步骤进行处理。 最后,我还计划使用容器化技术(如Docker)来实现我的研究项目的可移植性。通过将我的环境和依赖项封装在一个容器中,我可以确保其他人能够在不同的计算机和操作系统上轻松地运行我的代码和分析。 综上所述,第4周的可重复研究项目将继续探索一系列工具和技术,旨在提高我的研究项目的可重复性和透明度。通过使用版本控制系统、Jupyter Notebook、数据处理和清洗措施以及容器化技术,我将确保我的研究成果可以被其他人准确地重现和验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值