Journal First
Q:活动调度
最开始的思路大概是
用一个结构体数组,两个元素分别是其实和结束时间(后来发现还不如直接用两个数组分别表示起始与结束)。
然后遍历开始的时间,找到最晚开始的时间,从0遍历到那个值,遇到开始/结束时间计数器加/减1,每次计数器发生改变就将新值存入一个结果数组中,遍历之后返回结果数组中的最大值。
代码如下
#define SIZE 1000005
#include<stdio.h>
#include <iostream>
#include<algorithm>
using namespace std;
typedef struct period {
long int Si;
long int Fi;
}Period;
Period meet[SIZE];
long int temp[SIZE];//设成全局变量防止内存溢出
int op_same_time[SIZE * 2];//用于存放同一时间进行的会议数
int numbe;
void Input();
int Core_Calc(Period* time, int num);
//int Find_the_last(period* time);//找到最后位置的Si
void Output(int ans);
int main()
{
int res;
Input();
res = Core_Calc(meet, numbe);
Output(res);
return 0;
}
void Input() {
scanf("%d", &numbe);
for (int i = 0; i < numbe; i++)
{
scanf("%d%d", &meet[i].Si, &meet[i].Fi);
}
}
int Core_Calc(Period time[], int num)
{
int endline;
int count = 0;
int k = 0;
for (int i = 0; i < num; i++)
{
temp[i] = time[i].Si;
}
endline = *max_element(temp, temp + num);
for (int i = 0; i <= endline; i++)
{
for (int j = 0; j < num; j++)
{
if (i == time[j].Fi)
{
count--;
op_same_time[k++] = count;
}
if (i == time[j].Si)
{
count++;
op_same_time[k++] = count;
}
}
}
return *max_element(op_same_time, op_same_time + k);
}
void Output(int ans)
{
printf("%d\n", ans);
}
其中用到了C++中函数*max_element()来返回一个数组中的最大值,且把所有大数组都定义为了全局变量防止内存溢出(放在局部变量时程序貌似会无法运行)。然而在lexue上面第三个用例会超过时间限制–TLE。
之后又找了一个思路,发现确实很有道理。
大概意思就是,先把起始和结束时间放在两个数组里面,先从小到大排序,然后再对两个数组同时进行遍历。
先上一下代码:
#define SIZE 1000005
#include<stdio.h>
#include <iostream>
#include<algorithm>
using namespace std;
typedef struct period {
long int Si;
long int Fi;
}Period;
Period meet[SIZE];
long int temps[SIZE];//设成全局变量防止内存溢出
long int tempf[SIZE];
int op_same_time[SIZE * 2];//用于存放同一时间进行的会议数
int numbe;
void Input();
int Core_Calc(Period* time, int num);
//int Find_the_last(period* time);//找到最后位置的Si
void Output(int ans);
int main()
{
int res;
Input();
res = Core_Calc(meet, numbe);
Output(res);
return 0;
}
void Input() {
scanf("%d", &numbe);
for (int i = 0; i < numbe; i++)
{
scanf("%d%d", &meet[i].Si, &meet[i].Fi);
}
}
int Core_Calc(Period time[], int num)
{
int endline;
int count = 0;
int k = 0,j = 0;
int tem=0;
for (int i = 0; i < num; i++)
{
temps[i] = time[i].Si;
tempf[i] = time[i].Fi;
}
sort(temps,temps+numbe);
sort(tempf,tempf+numbe);
while(k<numbe&&j<numbe)
{
if(temps[k]<tempf[j])
{
count++;
k++;
tem=max(count,tem);
}
else if(temps[k]>tempf[j])
{
count--;
j++;
tem=max(count,tem);
}
else
{
count--;
j++;
count++;
k++;
tem=max(count,tem);
}
}
return tem;
}
void Output(int ans)
{
printf("%d\n", ans);
}
核心while循环也不难理解,对于一个起始时间与一个结束时间,如果temps[i]<tempf[j],则意味着在某个活动结束时间之前,又有新活动开始了,则计数器+1,否则计数器-1,要特别注意的是,如果遇到两个值相等要单独处理。然后对返回值tem的取值用了C++中max()函数,每次刷新,更为方便。
最后想说一下这次学到的一些改正:
关于typedef声明结构体:
``typedef struct structname{
}yourname;
``