【算法设计】计算某个时间段的最多参会人数

liyudefly 2013-12-27 02:37:47
假设会议从开始到结束共S分钟,会议过程中随时可以有人加入,也随时可以有人退出,进入和退出的时间均有记录,现将会议分成X段,求每段内最多在一起开会的人数。
例如有个会议125分钟,分成了0~30,31~60,61~90,91~120,120~125这五段,即30,60,90,120这四个分割点,第一人3分钟进来,50分钟退出,第二人4分钟进来,一直到会议结束,第三人7分钟进来,20分钟退出,第四人15分钟进来80分钟退出,第五人25分钟进来,一直开到最后,那么每段内最多同时在开会的人数为:0~30,4人,31~60,4人,61~90,3人,91~120,2人,120~125,2人。
若有不清楚的地请提问,第一时间补充说明,分最多给两人,复制过来的可以,我没找到。。。
...全文
714 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
liyudefly 2013-12-27
  • 打赏
  • 举报
回复
感谢各位,尤其感谢14楼,这就是我想要的。
追_逐 2013-12-27
  • 打赏
  • 举报
回复
15楼的错了!
// 时间段杖举
enum EnTimeSeg
{
	EnFirstSeg,
	EnSecondSeg,
	EnThirdSeg,
	EnFourthSeg,
	EnFifthSeg
};

// 每个时间段的数据,其实可以直接用int 数组就OK了
struct STRU_SegInfo
{
	EnTimeSeg enSeg;
	int nMaxPerson;
};

struct STRU_SegInfo[5];
STRU_SegInfo[0].enSeg = EnFirstSeg,  STRU_SegInfo[0].nMaxPerson = 0;
STRU_SegInfo[1].enSeg = EnSecondSeg, STRU_SegInfo[1].nMaxPerson = 0;
STRU_SegInfo[2].enSeg = EnThirdSeg,  STRU_SegInfo[2].nMaxPerson = 0;
STRU_SegInfo[3].enSeg = EnFourthSeg, STRU_SegInfo[3].nMaxPerson = 0;
STRU_SegInfo[4].enSeg = EnFifthSeg,  STRU_SegInfo[4].nMaxPerson = 0;

// 用死循环处理这个东西很不好
while (1)
{
	enum EnTimeSeg enCurSeg;
	// 求得当前时间为哪个段
	// ... enCurSeg = ...;

	static int nCurPerson = 0;

	if (/*有人进*/)
	{
		++nCurPerson;
	}
	else	// 有人出
		--nCurPerson;

	switch (enCurSeg)
	{
	case EnFirstSeg:
		if (STRU_SegInfo[0].nMaxPerson < nCurPerson)
			STRU_SegInfo[0].nMaxPerson = nCurPerson;
		break;
	case EnSecondSeg:
		if (STRU_SegInfo[1].nMaxPerson < nCurPerson)
			STRU_SegInfo[1].nMaxPerson = nCurPerson;
		break;
	case EnThirdSeg:
		if (STRU_SegInfo[2].nMaxPerson < nCurPerson)
			STRU_SegInfo[2].nMaxPerson = nCurPerson;
		break;
	case EnFourthSeg:
		if (STRU_SegInfo[3].nMaxPerson < nCurPerson)
			STRU_SegInfo[3].nMaxPerson = nCurPerson;
		break;
	case EnFirstSeg:
		if (STRU_SegInfo[4].nMaxPerson < nCurPerson)
			STRU_SegInfo[4].nMaxPerson = nCurPerson;
		break;
	default:
		break;
	}
}
赵4老师 2013-12-27
  • 打赏
  • 举报
回复
我只会用最笨的办法:
//假设会议从开始到结束共S分钟,会议过程中随时可以有人加入,也随时可以有人退出,进入和退出的时间均有记录,
//现将会议分成X段,求每段内最多在一起开会的人数。
//例如有个会议125分钟,分成了0~30,31~60,61~90,91~120,120~125这五段,即30,60,90,120这四个分割点,
//第一人3分钟进来,50分钟退出,
//第二人4分钟进来,一直到会议结束,
//第三人7分钟进来,20分钟退出,
//第四人15分钟进来80分钟退出,
//第五人25分钟进来,一直开到最后,
//那么每段内最多同时在开会的人数为:
//0~30,4人,
//31~60,4人,
//61~90,3人,
//91~120,2人,
//120~125,2人。
#include <stdio.h>
static char d[5][125];
int h[5][2]={
    {  3, 50},
    {  4,124},
    {  7, 20},
    { 15, 80},
    { 25,124},
};
int g[5][2]={
    {  0, 30},
    { 31, 60},
    { 61, 90},
    { 91,120},
    {120,124},
};
int i,j,k,m,m1;
int main() {
    for (i=0;i<5;i++) {
        for (j=h[i][0];j<=h[i][1];j++) d[i][j]=1;
    }
    for (k=0;k<5;k++) {
        printf("%d~%d,",g[k][0],g[k][1]);
        m1=0;
        for (j=g[k][0];j<=g[k][1];j++) {
            m=0;
            for (i=0;i<5;i++) {
                m+=d[i][j];
            }
            if (m>m1) m1=m;
        }
        printf("%d\n",m1);
    }
    return 0;
}
//0~30,4
//31~60,4
//61~90,3
//91~120,2
//120~124,2
//
追_逐 2013-12-27
  • 打赏
  • 举报
回复
// 时间段杖举
enum EnTimeSeg
{
	EnFirstSeg,
	EnSecondSeg,
	EnThirdSeg,
	EnFourthSeg,
	EnFifthSeg
};

// 每个时间段的数据,其实可以直接用int 数组就OK了
struct STRU_SegInfo
{
	EnTimeSeg enSeg;
	int nMaxPerson;
};

struct STRU_SegInfo[5];
STRU_SegInfo[0].enSeg = EnFirstSeg,  STRU_SegInfo[0].nMaxPerson = 0;
STRU_SegInfo[1].enSeg = EnSecondSeg, STRU_SegInfo[1].nMaxPerson = 0;
STRU_SegInfo[2].enSeg = EnThirdSeg,  STRU_SegInfo[2].nMaxPerson = 0;
STRU_SegInfo[3].enSeg = EnFourthSeg, STRU_SegInfo[3].nMaxPerson = 0;
STRU_SegInfo[4].enSeg = EnFifthSeg,  STRU_SegInfo[4].nMaxPerson = 0;

// 用死循环处理这个东西很不好
while (1)
{
	// 判断有人进还是有人出
	{
		// 获取当前时间,判断属性哪个时间段
		// 如果是有人出则将当前时间段下nMaxPerson 减一
		// 如果是有人进则将当前时间段下nMaxPerson 加一
	}
}
AndyStevens 2013-12-27
  • 打赏
  • 举报
回复
这不就是最大连续字串之和问题吗? 把每条进出记录作为一个数组元素,进人则正值,出人则为负值,总时间分为几段把记录分为几个数组,每个数组第一个元素为进入该时间段前会议室人数。使用类似动态规划扫描算法,复杂度O(n); 附上之前写的扫描算法:
#include <stdio.h>
int max_sub_sum(int *a , int n)
{
	int max_sofar = a[0];
	int max_with_i = a[0];
	int i;
	
	for(i=1;i<n;i++)
	{
		max_with_i = max_with_i<0?a[i]:max_with_i+a[i];
		max_sofar = max_sofar>max_with_i?max_sofar:max_with_i;
	}
	return max_sofar;

}

int main()
{
	int a[]={-31,-41,-59,-26,53,-58,97,93,-23,-84,-23,-44,-56};
	int max_sub;
	max_sub = max_sub_sum(a,sizeof(a)/sizeof(int));
	printf("%d\n",max_sub);
	return 0;
}
derekrose 2013-12-27
  • 打赏
  • 举报
回复
引用 12 楼 derekrose 的回复:
第一人3分钟进来,50分钟退出,第二人4分钟进来,一直到会议结束,第三人7分钟进来,20分钟退出,第四人15分钟进来80分钟退出,第五人25分钟进来,一直开到最后 30 60 90 120 sort后 3+ 4+ 7+ 15+ 20- 25+ | 50- | 80- | |125- 125- 然后foreach max 1 2 3 4 4 4 | 4 | 3 | 2 | 2 cur 1 2 3 4 3 4 | 3 | 2 | | 1 0
排版乱了
derekrose 2013-12-27
  • 打赏
  • 举报
回复
第一人3分钟进来,50分钟退出,第二人4分钟进来,一直到会议结束,第三人7分钟进来,20分钟退出,第四人15分钟进来80分钟退出,第五人25分钟进来,一直开到最后 30 60 90 120 sort后 3+ 4+ 7+ 15+ 20- 25+ | 50- | 80- | |125- 125- 然后foreach max 1 2 3 4 4 4 | 4 | 3 | 2 | 2 cur 1 2 3 4 3 4 | 3 | 2 | | 1 0
  • 打赏
  • 举报
回复
引用 9 楼 truelance 的回复:
还有一种方法, 就是你把所有人入场, 出场, 时间段间隔点都看成事件, 重新按照事件的发生顺序进行排序. 然后按顺序处理, 只统计事件点的人数就行了, 这样和时间精度就无关了.
进栈出栈
derekrose 2013-12-27
  • 打赏
  • 举报
回复
每个阶段维护一个最大值和一个当前值 不行吗?
熊熊大叔 2013-12-27
  • 打赏
  • 举报
回复
还有一种方法, 就是你把所有人入场, 出场, 时间段间隔点都看成事件, 重新按照事件的发生顺序进行排序. 然后按顺序处理, 只统计事件点的人数就行了, 这样和时间精度就无关了.
熊熊大叔 2013-12-27
  • 打赏
  • 举报
回复
引用 7 楼 liyudefly 的回复:
引用 5 楼 truelance 的回复:
[quote=引用 4 楼 liyudefly 的回复:] [quote=引用 1 楼 truelance 的回复:] 每个时间段的人数是怎么统计的, 只要在这个时间段出现就算? 在这个时间段结束时在场? 还是超过50%时间在场?
不是只出现就算,比方说一个会议室,里面最多同时的人数,而不是只进过就算
逐分钟统计人数, 然后在每个时间段内取最大值[/quote] 实际上,是精确到了0.1秒的,而不是分钟,这里我把其它很多东西简化了,所以每分钟统计一个值记录不合适。[/quote] 你实际上是什么问题呢? 这个精度和算法的复杂度都是根据实际需求决定的. 比如说电信设备里记录电话起始时间还都能精确到0.001秒呢, 但是在做话务统计时都是用5秒做抽样, 因为这个精度就够了.
liyudefly 2013-12-27
  • 打赏
  • 举报
回复
引用 5 楼 truelance 的回复:
引用 4 楼 liyudefly 的回复:
[quote=引用 1 楼 truelance 的回复:] 每个时间段的人数是怎么统计的, 只要在这个时间段出现就算? 在这个时间段结束时在场? 还是超过50%时间在场?
不是只出现就算,比方说一个会议室,里面最多同时的人数,而不是只进过就算
逐分钟统计人数, 然后在每个时间段内取最大值[/quote] 实际上,是精确到了0.1秒的,而不是分钟,这里我把其它很多东西简化了,所以每分钟统计一个值记录不合适。
熊熊大叔 2013-12-27
  • 打赏
  • 举报
回复
我会告诉你电信设备里的话务量统计就是这么做的么 每个打电话的人开始结束时间,要知道每个时间段同时打电话的最多人数,并划出全天的变化曲线。是不是就是这个问题?
熊熊大叔 2013-12-27
  • 打赏
  • 举报
回复
引用 4 楼 liyudefly 的回复:
引用 1 楼 truelance 的回复:
每个时间段的人数是怎么统计的, 只要在这个时间段出现就算? 在这个时间段结束时在场? 还是超过50%时间在场?
不是只出现就算,比方说一个会议室,里面最多同时的人数,而不是只进过就算
逐分钟统计人数, 然后在每个时间段内取最大值
liyudefly 2013-12-27
  • 打赏
  • 举报
回复
引用 1 楼 truelance 的回复:
每个时间段的人数是怎么统计的, 只要在这个时间段出现就算? 在这个时间段结束时在场? 还是超过50%时间在场?
不是只出现就算,比方说一个会议室,里面最多同时的人数,而不是只进过就算
熊熊大叔 2013-12-27
  • 打赏
  • 举报
回复
如果出现就算,那么例子里第一时间段应该是5人
lm_whales 2013-12-27
  • 打赏
  • 举报
回复
1)128 Bits 掩码表示法 2)查表法,或者用switch 处理
熊熊大叔 2013-12-27
  • 打赏
  • 举报
回复
每个时间段的人数是怎么统计的, 只要在这个时间段出现就算? 在这个时间段结束时在场? 还是超过50%时间在场?

65,176

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧