SDU week10限时模拟 B-团队聚会

题目

样例输入

2
3
3
2020 06 28 15 00 00 2020 06 28 18 00 00 TT study
2020 06 29 10 00 00 2020 06 29 15 00 00 TT solving problems
2020 11 15 15 00 00 2020 11 17 23 00 00 TT play with his magic cat
4
2020 06 25 13 30 00 2020 06 25 15 30 00 hrz play
2020 06 26 13 30 00 2020 06 26 15 30 00 hrz study
2020 06 29 13 00 00 2020 06 29 15 00 00 hrz debug
2020 06 30 13 00 00 2020 06 30 15 00 00 hrz play
1
2020 06 01 00 00 00 2020 06 29 18 00 00 zjm study
2
1
1800 01 01 00 00 00 2200 01 01 00 00 00 sleep
0

样例输出

Scenario #1:
appointment possible from 01/01/1800 00:00:00 to 06/25/2020 13:30:00
appointment possible from 06/25/2020 15:30:00 to 06/26/2020 13:30:00
appointment possible from 06/26/2020 15:30:00 to 06/28/2020 15:00:00
appointment possible from 06/28/2020 18:00:00 to 06/29/2020 10:00:00
appointment possible from 06/29/2020 15:00:00 to 01/01/2200 00:00:00
Scenario #2:
no appointment possible

 

思路

首先,我们在存储时间时使用结构体 tim,该结构体只存一个时间段(事情开始的时间与事情结束的时间)。

在处理的时候分两次存储,首先对于每一个申请两个二维数组 b、e,分别存储每个助教的每一个事件的开始时间与结束时间。b、e不需要排序,本身数据就是有序的。

第二次存储时,申请一位数组 tim 存储每个助教、每个事件开始与结束的时间段,并根据时间先后对其进行排序。

(助教讲这道题的时候用的是 set ,可以去重,性能应该会比直接用数组更优)。

在存储时间段时,要注意存上最起始时间段1800.01.01 00:00:00,存在 tim[0]中,最后时间段2200.01.01 00:00:00,存在 tim[k+1]中(k为除去初始与末尾时间段的总数目)。

然后进行循环,遍历每个时间段寻找空闲时间段的 left 与 right。

注意,在判断left的时候,这个时间点不能等于某助教事件的开始时间点!!

其实我觉得对于一个小时的判断也是一个难点,需要从年份开始进行判断...

ps

我在写这道题的时候还有一个初版:

初版的思路是尺取法,维护一个绝对安全的范围与一个已经存在有人不能参会的范围。

对于只有2个助教的情况另行考虑。

但是这个写法实际上是针对时间段的,没办法判断在一个时间段内究竟是两个TA时间冲突还是一个TA的两件事情时间冲突,即没办法准确判断参会人数(也不是完全没办法,但是本来这个写法就比较麻烦,如果再加入其它变量进行判断就更麻烦,所以我就直接推翻重写了...)。

大概是由于因为会出现同一个TA时间撞车而没办法准确判断人数的情况,所以疯狂wa......(当然也有可能是算法有问题wa,但我觉得可能性不大)

 

A了的代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
using namespace std;

void out(int x)
{
	if (x < 10) cout << 0 << x;
	else cout << x;
}

struct tim
{
	int year, month, day, hour, minute, second;
	tim(int y = 1800, int m = 1, int d = 1, int h = 0, int min = 0, int s = 0)
	{
		year = y, month = m, day = d, hour = h, minute = min, second = s;
	}
	void giveTime(int y = 1800, int m = 1, int d = 1, int h = 0, int min = 0, int s = 0)
	{
		year = y, month = m, day = d, hour = h, minute = min, second = s;
	}
	bool operator<(const struct tim &p) const
	{
		if (year != p.year)
			return year < p.year;
		if (month != p.month)
			return month < p.month;
		if (day != p.day)
			return day < p.day;
		if (hour != p.hour)
			return hour < p.hour;
		if (minute != p.minute)
			return minute < p.minute;
		else
			return second < p.second;

	}

	bool operator==(const struct tim &p) const
	{
		return !(*this < p || p < *this);
	}
	bool operator!=(const struct tim &p) const
	{
		return *this < p || p < *this;
	}

	bool operator<=(const struct tim &p) const
	{
		return *this < p || p == *this;
	}

	bool operator>(const struct tim &p) const
	{
		return p < *this;
	}
	bool operator>=(const struct tim &p) const
	{
		return p <= *this;
	}

	void copy(struct tim &p)
	{
		year = p.year, month = p.month, day = p.day, hour = p.hour, minute = p.minute, second = p.second;
	}
	void out()
	{
		cout << year << "." << month << "." << day << " " << hour << ":" << minute << ":" << second << endl;
	}
}b[25][110],e[25][110], tim[4040];

struct tim beginn, endd(2200, 01, 01, 00, 00, 00);

bool enough(struct tim a, struct tim b)
{
	if (b < a) return false;

	if (b.year - a.year > 1) return true;
	b.month += (b.year - a.year) * 12;

	if (b.month - a.month > 1) return true;
	b.day += (b.month - a.month) * 30;

	if (b.day - a.day > 1) return true;
	b.hour += (b.day - a.day) * 24;

	if (b.hour - a.hour > 1) return true;
	b.minute += (b.hour - a.hour) * 60;
	b.second += (b.minute - a.minute) * 60;

	if (b.second - a.second >= 3600) return true;
	return false;
}


void print(struct tim &a, struct tim &b)
{
	cout << "appointment possible from ";
	out(a.month); cout << "/";
	out(a.day); cout << "/";
	out(a.year); cout << " ";
	out(a.hour); cout << ":";
	out(a.minute); cout << ":";
	out(a.second);
	cout << " to ";
	out(b.month); cout << "/";
	out(b.day); cout << "/";
	out(b.year); cout << " ";
	out(b.hour); cout << ":";
	out(b.minute); cout << ":";
	out(b.second); cout << endl;
}
string c;
int T, m, n, k;
int num[25];

bool beleft(int index) {
	if (index < 0 || index >= k + 1)return false;
	int tot = 0;
	for (int i = 1; i <= m; i++)
	{
		if (num[i] == 0){	tot++; continue; }//这助教没事,肯定能开会
		if (tim[index] < b[i][1]) { tot++; continue; }//在所有事情之前
		if (tim[index] == b[i][1]) break;//一件事情的开始
		if (e[i][num[i]] <= tim[index] && endd > tim[index]) { tot++; continue; }//在所有事情之后
		for (int j = 1; j <= num[i]; j++)
		{
			if (b[i][j] <= tim[index] && tim[index] < e[i][j]) break;//这助教在这个时间点有事
			if (j + 1 <= num[i] && e[i][j] <= tim[index] && b[i][j + 1] > tim[index]) {tot++; break; }
			//这个left在助教有事的两件事之间
		}
	}
	//cout << "tot:" << tot << endl;
	if (tot >= 2 && tot >= m - 1) return true;
	return false;
}

bool beright(int index) {
	if (index > k + 1 || index <= 0) return false;
	
	int tot = 0;
	for (int i = 1; i <= m; i++)
	{
		if (num[i] == 0) { tot++; continue; }//这助教没事,肯定能开会
		if (tim[index] <= b[i][1] && tim[index] > beginn) { tot++; continue; }//在所有事情之前
		if (tim[index] > e[i][num[i]]) { tot++; continue; }//在所有事情之后
		if (tim[index] == e[i][num[i]]) continue;//前面那段时间有事
		for (int j = 1; j <= num[i]; j++) {
			if (b[i][j] < tim[index] && tim[index] <= e[i][j]) break;//这助教在这个时间点有事
			if (j + 1 <= num[i] && e[i][j] < tim[index] && b[i][j + 1] >= tim[index]) {tot++; break; }
			//这个left在助教有事的两件事之间
		}
	}
	if (tot >= 2 && tot >= m - 1) return true;
	return false;
}

int main()
{
	cin >> T;
	for (int u = 1; u <= T; u++)//每组
	{
		memset(num, 0, sizeof(num));
		memset(b, 0, sizeof(b));
		memset(e, 0, sizeof(e));
		memset(tim, 0, sizeof(tim));
		cin >> m;
		k = 0;
		tim[0].copy(beginn);
		for (int i = 1; i <= m; i++)//每个助教
		{
			cin >> num[i];
			for (int j = 1; j <= num[i]; j++)
			{
				cin >> b[i][j].year >> b[i][j].month >> b[i][j].day >> b[i][j].hour >> b[i][j].minute >> b[i][j].second
					>> e[i][j].year >> e[i][j].month >> e[i][j].day >> e[i][j].hour >> e[i][j].minute >> e[i][j].second;

				getline(cin, c);
				tim[++k].copy(b[i][j]);
				tim[++k].copy(e[i][j]);
			}
		}
		
		tim[k + 1].copy(endd);
		sort(tim, tim + k + 2);
		bool have = false;
		int left = 0, right = 1;
		cout << "Scenario #" << u << ":" << endl;
		while (left <= k && right <= k)
		{
			if (right > k + 1)break;
			while (right <= k + 1 && beright(right))right++;
			right--;
			if (enough(tim[left], tim[right]))
			{
				print(tim[left], tim[right]);
				have = true;
			}

			left = right + 1;
			
			while (left <= k + 1 && !beleft(left))left++;
			right = left + 1;
		}
	

		if (!have) cout << "no appointment possible" << endl;
		cout << endl;

	}
	system("Pause");
}

 

疯狂wa的初版代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
using namespace std;

void out(int x)
{
	if (x < 10) cout << 0 << x;
	else cout << x;
}

struct eve
{
	int TA;
	int fyear, fmon, fday, fhour, fmin, fsec,
		tyear, tmon, tday, thour, tmin, tsec;
	eve(int y = 1800, int m = 1, int d = 1, int h = 0, int min = 0, int s = 0,
		int yy = 1800, int mm = 1, int dd = 1, int hh = 0, int minm = 0, int ss = 0)
	{
		fyear = y, fmon = m, fday = d, fhour = h, fmin = min, fsec = s;
		tyear = y, tmon = m, tday = d, thour = h, tmin = min, tsec = s;
	}
	bool operator<(const struct eve &p)const
	{
		if (fyear != p.fyear)
			return fyear < p.fyear;
		if (fmon != p.fmon)
			return fmon < p.fmon;
		if (fday != p.fday)
			return fday < p.fday;
		if (fhour != p.fhour)
			return fhour < p.fhour;
		if (fmin != p.fmin)
			return fmin < p.fmin;
		if (fsec != p.fsec)
			return fsec < p.fsec;
		if (tyear != p.tyear)
			return tyear > p.tyear;
		if (tmon != p.tmon)
			return tmon > p.tmon;
		if (tday != p.tday)
			return tday > p.tday;
		if (thour != p.thour)
			return thour > p.thour;
		if (tmin != p.tmin)
			return tmin > p.tmin;
		if (tsec != p.tsec)
			return tsec > p.tsec;
		else
			return TA < p.TA;
	}

	bool operator==(const struct eve &p) const
	{
		return !(*this < p || p < *this);
	}
	bool operator!=(const struct eve &p) const
	{
		return *this < p || p < *this;
	}

	bool operator<=(const struct eve &p) const
	{
		return *this < p || p == *this;
	}

	bool operator>(const struct eve &p) const
	{
		return p <= *this;
	}
	bool operator>=(const struct eve &p) const
	{
		return p < *this;
	}

	void out()
	{
		cout << fyear << "." << fmon << "." << fday << " " << fhour << ":" << fmin << ":" << fsec << " to "
			<< tyear << "." << tmon << "." << tday << " " << thour << ":" << tmin << ":" << tsec << endl;
	}
}eve[2020];


struct tim
{
	int year, month, day, hour, minute, second;
	tim(int y = 1800, int m = 1, int d = 1, int h = 0, int min = 0, int s = 0)
	{
		year = y, month = m, day = d, hour = h, minute = min, second = s;
	}
	void giveTime(int y = 1800, int m = 1, int d = 1, int h = 0, int min = 0, int s = 0)
	{
		year = y, month = m, day = d, hour = h, minute = min, second = s;
	}
	bool operator<(const struct tim &p) const
	{
		if (year != p.year)
			return year < p.year;
		if (month != p.month)
			return month < p.month;
		if (day != p.day)
			return day < p.day;
		if (hour != p.hour)
			return hour < p.hour;
		if (minute != p.minute)
			return minute < p.minute;
		else
			return second < p.second;

	}

	bool operator==(const struct tim &p) const
	{
		return !(*this < p || p < *this);
	}
	bool operator!=(const struct tim &p) const
	{
		return *this < p || p < *this;
	}

	bool operator<=(const struct tim &p) const
	{
		return *this < p || p == *this;
	}

	bool operator>(const struct tim &p) const
	{
		return p <= *this;
	}
	bool operator>=(const struct tim &p) const
	{
		return p < *this;
	}

	void copy(struct tim &p)
	{
		year = p.year, month = p.month, day = p.day, hour = p.hour, minute = p.minute, second = p.second;
	}
	void out()
	{
		cout << year << "." << month << "." << day << " " << hour << ":" << minute << ":" << second << endl;
	}
};



bool enough(struct tim a, struct tim b)
{
	if (b < a) return false;

	if (b.year - a.year >= 2) return true;
	b.month += (b.year - a.year) * 12;

	if (b.month - a.month >= 2) return true;
	b.day += (b.month - a.month) * 30;

	if (b.day - a.day >= 2) return true;
	b.hour += (b.day - a.day) * 24;

	if (b.hour - a.hour >= 2) return true;
	b.minute += (b.hour - a.hour) * 60;
	b.second += (b.minute - a.minute) * 60;

	if (b.second - a.second >= 3600) return true;
	return false;
}


void print(struct tim &a, struct tim &b)
{
	cout << "appointment possible from ";
	out(a.month); cout << "/";
	out(a.day); cout << "/";
	out(a.year); cout << " ";
	out(a.hour); cout << ":";
	out(a.minute); cout << ":";
	out(a.second);
	cout << " to ";
	out(b.month); cout << "/";
	out(b.day); cout << "/";
	out(b.year); cout << " ";
	out(b.hour); cout << ":";
	out(b.minute); cout << ":";
	out(b.second); cout << endl;
}
string c;
int T, m, n;

int main()
{
	cin >> T;
	for (int u = 1; u <= T; u++)//每组
	{

		cin >> m;
		int k = 0;
		for (int i = 0; i < m; i++)//每个助教
		{
			cin >> n;
			for (int j = 0; j < n; j++)
			{
				eve[k].TA = i + 1;
				cin >> eve[k].fyear >> eve[k].fmon >> eve[k].fday >> eve[k].fhour >> eve[k].fmin >> eve[k].fsec
					>> eve[k].tyear >> eve[k].tmon >> eve[k].tday >> eve[k].thour >> eve[k].tmin >> eve[k].tsec;

				getline(cin, c);
				k++;
			}
		}
		
		sort(eve, eve + k);

		struct tim safeBegin, safeEnd(eve[0].fyear, eve[0].fmon, eve[0].fday, eve[0].fhour, eve[0].fmin, eve[0].fsec),
			dangerBegin, dangerEnd(eve[0].tyear, eve[0].tmon, eve[0].tday, eve[0].thour, eve[0].tmin, eve[0].tsec),
			danger;
		dangerBegin.copy(safeEnd);

		cout << "Scenario #" << u << ":" << endl;
		//cout << "m:" << m << endl;
		bool have = false;
		if (m == 2)
		{
			if (enough(safeBegin, safeEnd))
			{
				print(safeBegin, safeEnd);
				have = true;
			}
			for (int i = 1; i < k; i++)
			{

				struct tim begin(eve[i].fyear, eve[i].fmon, eve[i].fday, eve[i].fhour, eve[i].fmin, eve[i].fsec);
				struct tim end(eve[i].tyear, eve[i].tmon, eve[i].tday, eve[i].thour, eve[i].tmin, eve[i].tsec);
				
				if (dangerEnd < begin)
				{
					
					safeBegin.copy(dangerEnd);
					safeEnd.copy(begin);
					if (enough(safeBegin, safeEnd))
					{
						print(safeBegin, safeEnd);
						have = true;
					}
					dangerBegin.copy(safeEnd);
				}

				if (dangerEnd < end)
					dangerEnd.copy(end);

			}
			safeBegin.copy(dangerEnd);
			safeEnd.giveTime(2200, 1, 1, 0, 0, 0);
		
			if (enough(safeBegin, safeEnd))
			{
				print(safeBegin, safeEnd);
				have = true;
			}

		}
		else if (m > 2)
		{


			for (int i = 1; i < k; i++)
			{

				struct tim begin(eve[i].fyear, eve[i].fmon, eve[i].fday, eve[i].fhour, eve[i].fmin, eve[i].fsec);
				struct tim end(eve[i].tyear, eve[i].tmon, eve[i].tday, eve[i].thour, eve[i].tmin, eve[i].tsec);
				cout << endl;
				cout << "now:" << endl;
				begin.out();
				end.out();
				cout << "safe" << endl;
				safeBegin.out();
				safeEnd.out();
				cout << "danger:" << endl;
				dangerBegin.out();
				dangerEnd.out();
				safeEnd.copy(begin);
				if (enough(safeBegin, safeEnd))
				{
					cout << "aaa" << endl;
					print(safeBegin, safeEnd);
					have = true;
				}

				if (begin < dangerEnd)
				{
					if (end < dangerEnd)//safeBegin
						safeBegin.copy(end);
					else
						safeBegin.copy(dangerEnd);

					if (danger < safeBegin)//danger
						danger = safeBegin;
					else
						safeBegin = danger;
					
					if (end < dangerEnd)//dangerEnd
						dangerEnd.copy(dangerEnd);
					else
						dangerEnd.copy(end);
                    
					dangerBegin.copy(safeBegin);
				}			
				else 
				{
						dangerBegin.copy(begin);
						dangerEnd.copy(end);
				}
			}

			safeEnd.giveTime(2200, 1, 1, 0, 0, 0);
			if (enough(safeBegin, safeEnd))
			{
				print(safeBegin, safeEnd);
				have = true;
			}
		}

		if (!have) cout << "no appointment possible" << endl;
		cout << endl;

	}
	system("Pause");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值