题目:申请会场问题
有n个活动申请使用会场,每个会场只按整点时段接待活动,同时每个会场任意时段内最多接待一个活动。比如某个活动起始时间是2点,结束时间是4点,则意味着该活动从2点00分到4点59分都要占用会场。如果要把n场活动全部举行,最少需要几个会场。
输入格式:
第一行输入活动的个数n,n<100。第二行依次输入n场活动的起始时间(整数)。第三行依次输入n场活动的结束时间(整数)。
输出格式:
输出最少需要的会场个数。
输入样例:
在这里给出一组输入。例如:
3
2 3 0
4 5 2
输出样例:
在这里给出相应的输出。例如:
2
解法一:较多看到的解法(存在问题)
以选择最早结束时间作为贪心策略,但此做法只能保证第一次安排的会议数最多,存在后效性,不能使全局最优。但可以用来解决求会场只有一个的情况下能安排的最多会议数问题。
存在问题的样例:
解法一得到的结果为4,解法二得到的结果为3(三个会场就足够了)
6
90 8 18 16 83 39
98 32 48 82 84 89
解法一:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct time { int be, en; }ti[110];
vector<struct time> v;
bool cmp(struct time a, struct time b) { return a.en < b.en; };
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> ti[i].be;
for (int i = 0; i < n; i++)
cin >> ti[i].en;
sort(ti, ti + n, cmp);
for (int i = 0; i < n; i++)
v.push_back(ti[i]);
int ans = 0;
while (v.size())
{
int en = -1;
for (int i = 0; i < v.size(); i++)
{
if (v[i].be > en)
{
en = v[i].en;
v.erase(v.begin() + i);
i--;
}
}
ans++;
}
cout << ans << '\n';
return 0;
}
解法二:
1:将开始时间和结束时间分别从小到大排序,首先取最早开始时间和最早结束时间,第一视角在结束时间最早的会场(因为对于结束时间从小到大遍历)
2:当开始时间小于结束时间时,说明这个会议开始的很早,不能排在任意一个会议结束之后开始(当前遍历的为结束时间最早,这种情况都不能安排,其他情况更不可能),因此需要单独给它开辟一个会场,因此会场计数+1。
3:当开始时间大于结束时间时,说明这个结束时间最早的会场可以安排开始时间为当前遍历值的会议,但同时,本会场可能不再是结束时间最早的,需要更新,因此对结束时间进行更新取后面一个。
#include<iostream>
#include<algorithm>
using namespace std;
int beg[110], en[110];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> beg[i];
for (int i = 0; i < n; i++)
cin >> en[i];
sort(beg, beg + n);
sort(en, en + n);
int j = 0, ans = 0;
for (int i = 0; i < n; i++)
{
if (beg[i] <= en[j])//本题要求不能马上开始,因此为<=
ans++;
else
j++;
}
cout << ans << '\n';
return 0;
}