标签:
题目:
有一组活动,我们需要将它们安排到一些教室,任意活动都可以在任意教室进行。我们希望使用最少的教室完成所有活动。
设计一个高效的贪心算法求每个活动应该在哪个教室进行。
分析:
本题是对书中活动选择问题的一个扩展。在活动选择问题中,我们要求的是一个最大兼容活动集,也就是在所有时间内时间不重叠的最多的活动集合。
易知,这样一个活动集,就是一个教室最多能够举办的活动集。所以剩下的活动一定不能和该活动集内的活动在同一个教室举行。我们不断对剩下的活动使用贪心算法,需要多少次贪心能够选取完所有的活动,就最少需要几个教室。
我们首先对所有活动按结束时间排序。遍历所有活动,如果下一个活动开始时间比某教室中最后一个活动结束时间晚,则加入该教室。如果不能加入已使用的任何教室,则需要新开一个教室。
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
typedef pair<int,int> Acti;//用起始时间和结束时间的pair表示一个活动。
void party(vector<Acti>& acti_vec)
{
sort(acti_vec.begin(),acti_vec.end(),[](const Acti& a,const Acti& b){return a.second < b.second;});//按结束时间对所有活动排序。
vector<vector<Acti>> classroom;//教室列表。
vector<Acti> classroom1;
classroom1.push_back(*acti_vec.begin());//初始化第一个教室,将结束时间最早的活动放入。
classroom.push_back(classroom1);//将第一个教室加入教室列表。
for(int i = 1;i<(int)acti_vec.size();i++)//遍历一遍活动列表。
{
int j;
for(j = 0;j < (int)classroom.size();j++)
{
if(acti_vec[i].first >= (*(classroom[j].end()-1)).second)//如果该活动的开始时间比某教室目前为止最后一个活动结束结束时间晚,则加入该教室。
{
classroom[j].push_back(acti_vec[i]);
break;
}
}
if(j == (int)classroom.size())//如果无法加入当前任何一个教室,则需要一个新的教室。
{
vector<Acti> classroom_temp;
classroom_temp.push_back(acti_vec[i]);
classroom.push_back(classroom_temp);
}
}
for(int i = 0;i < (int)classroom.size();i++)//对每一个教室,按起始时间 结束时间输出每一个活动。
{
cout<<"classroom "<<i+1<<":"<<endl;
for(int j = 0;j < (int)classroom[i].size();j++)
{
cout<<classroom[i][j].first<<" "<<classroom[i][j].second<<endl;
}
}
}
int main()
{
vector<Acti> acti_vec = {
{1,4},
{3,5},
{0,6},
{5,7},
{3,9},
{5,9},
{6,10},
{8,11},
{8,12},
{2,14},
{12,16}
};
party(acti_vec);
return 0;
}
在本题解法的第一次实现中犯了一个错误,错误的使用了迭代器,然而,由于在遍历的过程中,要向classroom的vector中添加元素,当vector被修改后,原先的迭代器都会失效,所以不能使用迭代器,而改用int下标。
标签:
原文地址:http://www.cnblogs.com/StartoverX/p/4608412.html