时间问题:贝壳2018笔试题   教室占用冲突

贝壳2018   教室占用冲突

1、题目描述:

        n个社团占用同一间教室,占用时间分别为 [li, ri]。占用时间可能发生冲突,去掉其中一个社团的申请后不发生冲突的方法有几种。

输入:

        第一行:整数n,表示社团数。(1 <= n <= 5000)
        第二行:n个区间,代表第i个社团的占用时间范围[li, ri]。

输出:

        第一行:整数m,代表删除方式的数量。(每次只能删除一个社团)
        第二行:m个整数,可以删除的社团编号,从小到大排列。


样例输入1:

        3
        3 10
        20 30
        1 3

样例输出1:

        3
        1 2 3

样例输入2:

        4
        3 10
        20 30
        1 3
        1 39

样例输出2:

        1
        4

样例输入3:

        3
        1 5
        2 6
        3 7

样例输出3:

        0
*/

2、题解-敲代码

1、对所有区间,按左边界进行排序,产生升序序列;

2、遍历升序序列,找到第一个冲突点(有前后两个社团发生冲突,”前一个社团“ 的右边界 > ”后一个社团“ 的左边界),记录这两个社团;以 “后一个社团” 的下一个社团作为 “新起点”,开始继续遍历比较,如果有第二个冲突点,则冲突无法避免,返回0;

3、如果整个遍历没有发生冲突,则无冲突,返回0;

4、如果只发生了一次冲突

(1)判断 “前一个社团” 是否和 ”新起点“ 及其之后的社团发生冲突

(2)判断 “后一个社团” 是否和 ”新起点“ 及其之后的社团发生冲突

(3)如果两个都与后面发生冲突,则冲突无法避免,返回0;

(4)如果两个都不与后面发生冲突,则删除任意一个社团都可以避免冲突,返回2;

(4)如果只有一个冲突,另一个不冲突,则删除冲突的那一个,返回1。

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;


int main()
{
	int n;
	cin >> n;
	multimap<int, vector<int>> mp;       //{li, {ri, i}}   左,右,编号
	for (int i = 0; i < n; i++)
	{
		int x, y;
		cin >> x >> y;
		mp.insert({ x,{y, i+1} });
	}

	bool first_conflict = 0;  
	auto it11 = mp.end();        //记录冲突点第一个社团
	auto it22 = it11;            //记录冲突点第二个社团
	for (auto it1 = mp.begin(); it1 != --mp.end(); it1++) //
	{
		auto it2 = next(it1);
		if (it1->second[0] > it2->first)       //冲突
		{
			if (first_conflict == 0)      //是第一次发生冲突
			{
				it11 = it1;
				it22 = it2;
				first_conflict = 1;

				it1 = it2;//跳过it1, it2,判断后面是否还会发生冲突
			}
			else                         //第二次发生冲突
			{
				cout << 0;
				return 0;
			}
		}
	}
	if (first_conflict == 0)         //一次冲突也没有发生
	{
		cout << n << endl;
		for (int i = 1; i <= n; i++)
		{
			if (i < n)
				cout << i << ' ';
			else
				cout << i;
		}
		return 0;
	}


	//对于只发生一次冲突,分别将发生冲突的社团放入,查看是否会避免冲突
	int flag1 = 1;
	int flag2 = 1;
	if (next(it22) == mp.end() || it11->second[0] <= next(it22)->first)    //it11与之后的社团比较,查看是否会避免冲突
	{
		//it11不冲突
		flag1 = 0;
	}
	if (next(it22) == mp.end() || it22->second[0] <= next(it22)->first)     //it22与之后的社团比较,查看是否会避免冲突
	{
		//it22不冲突
		flag2 = 0;
	}

	if (flag1 && flag2)      //两个都与后面冲突,删除任意一个都无效
	{
		cout << 0;
	}
	else if (!flag1&& !flag2)      //两个都不与后面冲突,则删除任意一个即可
	{
		vector<int> ans = { it11->second[1], it22->second[1] };
		sort(ans.begin(), ans.end());
		cout << 2 << endl;
		cout << ans[0] << ' ' << ans[1];
	}
	else if(flag1 && !flag2)          //11与后面冲突,22与后面不冲突
	{
		cout << 1 << endl;
		cout << it11->second[1];
	}
	else if (!flag1 && flag2)          //11与后面不冲突,22与后面冲突
	{
		cout << 1 << endl;
		cout << it22->second[1];
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值