• 会场安排问题(贪心 两种方法)


    Description

    假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排。(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点着有不同颜色的最小着色数,相应于要找的最小会场数。) 对于给定的k个待安排的活动,计算使用最少会场的时间表。

    Input

    输入数据的第一行有1 个正整数k(k≤10000),表示有k个待安排的活动。接下来的k行中,每行有2个正整数,分别表示k个待安排的活动开始时间和结束时间。时间以0 点开始的分钟计。

    Output

    输出一个整数,表示最少会场数。

    Sample Input

    5
    1 23
    12 28
    25 35
    27 80
    36 50
    

    Sample Output

    3
    

    将开始时间和结束时间分别存为一个数组

    然后进行降序排序

    从第i个活动开始时间与第j个活动结束时间作比较

    如果开始时间大于等于结束时间,说明不用增加会场,就当第j个活动结束了,然后j++

    开始时间小于结束时间时,需要增加会场,ans++,第j个活动可以当还没结束,所以j不用动,直到遇到开始时间大于等于第j个活动结束时间的

    算法时间复杂度:$O(nlogn)$

    c++,sort:

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(NULL);
    	cout.tie(NULL);
    
    	int n, i, Begins[10002], Ends[10002];	// Begins开始时间, Ends结束时间
    	cin >> n;
    	for (i = 0; i < n; i++)
    		cin >> Begins[i] >> Ends[i];
    	sort(Begins, Begins + n);		// 升序排序
    	sort(Ends, Ends + n);			// 升序排序
    	int j = 0, ans = 0;
    	for (i = 0; i < n; i++)
    		if (Begins[i] < Ends[j])	// 如果开始时间小于结束时间, 会场数加1
    			ans++;
    		else						// 开始时间大于等于结束时间, 会场不用增加, 换下一家活动
    			j++;
    	cout << ans << endl;
    	return 0;
    }
    

    c,qsort:

    #include <stdio.h>
    #include <stdlib.h>
    
    int cmp(const void* a, const void* b)
    {
    	return *(int *)a - *(int *)b;
    }
    
    int main()
    {
    	int n, i, begins[10002], ends[10002];
    	scanf("%d", &n);
    	for (i = 0; i < n; i++)
    		scanf("%d%d", &begins[i], &ends[i]);
    	qsort(begins, n, sizeof(int), cmp);
    	qsort(ends, n, sizeof(int), cmp);
    	int j = 0, ans = 0;
    	for (i = 0; i < n; i++)
    		if(begins[i] < ends[j])
    			ans++;
    		else
    			j++;
    	printf("%d
    ", ans);
    	return 0;
    }
    

    还有一种时间复杂度$O(n^2)$的方法;

    比活动安排问题多出一个数组用来存储会场当前的状况

    #include <bits/stdc++.h>
    
    using namespace std;
    
    struct Activity
    {
    	int begin;			// 开始时间
    	int end;			// 结束时间
    }activity[10002];		// 活动
    
    bool cmp(Activity a, Activity b)
    {
    	return a.begin < b.begin;
    }
    
    int conference[10002];	// 会场
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(NULL);
    	cout.tie(NULL);
    	int n;
    	cin >> n;
    	for (int i = 0; i < n; i++)
    		cin >> activity[i].begin >> activity[i].end;
    	sort(activity, activity + n, cmp);		// 按开始时间升序排序
    	int ans = 0;
    	for (int i = 0; i < n; i++)
    	{
    		int temp = ans;
    		for (int j = 0; j <= temp; j++)		// 从已经有的会场找需不需要新会场, 不需要就更新结束时间
    		{
    			if (activity[i].begin >= conference[j])
    			{
    				if (conference[j] == 0)		// 需要新会场
    					ans++;
    				conference[j] = activity[i].end;	// 更新会场结束时间
    				break;
    			}
    		}
    	}
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    重写/覆盖基类的事件
    关于“日志”的输出控制
    WPF中DataGrid垂直滚动条滚动后导致每行CheckBox选择错乱
    WPF窗体应用程序开发
    C# 操作自定义config文件
    WPF绑定数据源之RelativeSource
    C# http请求 设置代理(标题可以作为搜索关键字)
    前端加载特效
    实现不同的项目,用不同的git 账号提交
    Casbin 使用记录
  • 原文地址:https://www.cnblogs.com/yanhua-tj/p/13996563.html
Copyright © 2020-2023  润新知