Greedy——活动选择问题

本文介绍如何通过贪心算法解决活动选择问题,即在一系列活动中找出最大的互不冲突的活动子集。文章提供了算法的伪代码及C++实现,并解释了贪心算法的关键特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

活动选择问题:就是给定一组活动的开始时间和结束时间,然后他们都需要使用到一个资源,这个资源每次只有一个活动可以用,要求求出一个最大的相互兼容的活动子集。

首先定义了一个集合Sij = {ak S :fi sk < fk sj} , 其中S就是所有活动的集合,fi是活动ai的完成时间si是活动ai的开始时间。

这道题如果是用DP来解的话,就需要找到最优解的递归方程(其中c[i,j]是集合Sij中的最大兼容活动的个数):

然后根据DP自底向上的解答方法进行求解,过程和矩阵连乘的差不多。

然而,根据下面的定理,我们可以用贪心的策略来解答这道题目:


这样子就将DP的两个子问题变成了只有一个子问题,而且由于将结束时间已升序排序,所以要求出fm也是很简单的。

接下来的工资就变得很简单了,看下面的伪代码和图片即可

RECURSIVE-ACTIVITY-SELECTOR(s, f, i, j)
1 m ← i + 1
2 while m  < j and sm < fi ▹ Find the first activity in Sij.
3     do m ← m + 1
4 if m < j
5    then return {am} ∪ RECURSIVE-ACTIVITY-SELECTOR(s, f, m, j)
6    else return Ø
下面的图片是利用上面的递归算法求解的过程



下面是代码,将递归改为迭代来实现。

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

struct Activity
{
	int s; //start time
	int f; //finish time
};

bool cmp(Activity A,Activity B)
{
	return A.f<B.f;
}

int main()
{
	Activity act[100];
	Activity temp[100];
	int n;
	cout<<"一共有多少个活动:";
	cin>>n;
	cout<<"输入每个活动的开始时间和结束时间:"<<endl;
	for(int i=0;i<n;i++)
		cin>>act[i].s>>act[i].f;
	sort(act,act+n,cmp);

	int k=0;
	temp[k]=act[0];
	for(i=1;i<n;i++)
	{
		while(act[i].s >= temp[k].f)
		{
			k++;
			temp[k]=act[i];
		}
	}
	cout<<"最后选择的兼容的活动的开始时间和结束时间如下:"<<endl;
	for(i=0;i<=k;i++)
		cout<<temp[i].s<<"  "<<temp[i].f<<endl;
	return 0;
}

运行结果:



运用贪心解决的问题具有两个特点:贪心选择性质和最优子结构

贪心选择性质:

一个全局最优解可以通过局部最优选择来达到,就是说,当我们做选择的时候,我们只考虑对当前问题最佳的选择而不考虑子问题的结果。这个和DP是不一样的,在DP中,每一步都要做出选择,但是这些选择依赖于子问题的解。但是在贪心算法中,所做的当前选择可能会依赖于已经做出的所有选择,但不依赖于有待做出的选择或者是子问题的解,所以DP是自底向上的,而贪心是自顶向下的。

最优子结构:

对于一个问题来说,如果它的一个最优解包含了其子问题的最优解,则说该问题具有最优子结构。

在贪心中,假设一个贪心选择后得到一个子问题,真正要做的是证明这个子问题的最优解与所做的贪心选择合并后,的确可以得到原问题的一个最优解。


Requirement: I. Query database with SQL Server. (30’, 2’ for each) 1. Create a table named Student using command Create Table. The table structure is as follows: Column Type Length Note ID Varchar 20 Student’s ID Name Varchar 10 Student’s Name Age Int Student’s Age Department Varchar 30 Student’s Dept. 2. Create a table named Course using command Create Table. The table structure is as follows: Column Type Length Note CourseID Varchar 15 Course’s ID CourseName Varchar 30 Course’s Name CourseBefore Varchar 15 Previous Course 3. Create a table named Choose using command Create Table. The table structure is as follows: Column Type Length Note ID Varchar 20 Student’s ID CourseID Varchar 15 Course’s ID Score Dec 5,2 Student’s Score 4. Insert 3 records into table Student using command Insert. ID Name Age Department 00001 ZhangSan 20 Computer Science 00002 LiSi 19 Computer Science 00003 WangWu 21 Computer Science 5. Insert 3 records into table Course using command Insert CourseID CourseName CourseBefore C1 Introduction to Computer - C2 PASCAL Programming Language C1 C3 Data Structure C2 6. Insert 7 records into table Choose using command Insert ID CourseID Score 00001 C1 95 00001 C2 80 00001 C3 84 00002 C1 80 00002 C2 85 00003 C1 78 00003 C3 70 7. Select the students’ ID and Name in Computer Science department using command select. 8. Select the students’ ID, Name, CourseName and Score using command select. 9. Select all students’ Information in descending order of the students’ ID. 10. Select every student’s average score. 11. Select the number of courses a student has chosen. 12. Select the number of students choosing a specific course. 13. Select the students’ ID who have chosen course C1 and got score over 80. 14. Select the students’ ID who have chosen course C2. 15. Select the average age of students in every department. II. Design a MIS for Computer Science college of SCUT. (45’) It is used to manage the information about course
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值