大一新生第一次写会场安排问题的辛酸经历

  如题,作为一个计算机专业的大一新生,开学前还是对电脑一窍不通的的小白,在学习了近一个学期的程序设计基础后,别的不敢说,至少打字的速度是呈几何倍增的。邻近期末,想着刷刷学校网站的题目,好家伙,迎头就来了一个会场安排的经典问题。解决这题,真是为难我这平庸的脑瓜了。

   好吧,初看这题,毫无头绪,想了十分钟后,大致明白了。先解决输入的问题,一开始想要一个一个输入,不过稍微细想就觉得自己太傻,直接输入怎么保存数据的位置,然后就自然而然地用数组来输入会场时间(用一维还是二维我还考虑了下,后来觉得二维可能比一维更难处理,就放弃了二维)。

  第二个要解决的点,想要会场能安排的活动最多,就必须满足1.每次能挑选的活动中(即下一个活动的开始时间大于上一个活动的结束时间),2.选结束时间最小的活动,满足这两个条件,就能保证后面安排更多的活动。(这就是我一开始的想法,其实是有点瑕疵的,所以我后来写代码的时候就吃了个大亏(;´༎ຶД༎ຶ`) )

  开始解决问题,首先,第一个活动的安排是挺重要的,不过他的限制条件只有一条,那就是结束时间最小的活动(因为所有的活动都有可能成为第一次活动,所以第一个条件可以忽略,故只考虑第二个条件)

min_idex=1,min=a[1];//活动结束时间存储在a[1],a[3]	...开始时间存储在a[0],a[2]...
for(i=min_idex;i<n;i=i+2)//找出符合条件的首活动
	{
		if(min>=a[i])
		{
			min=a[i];
			min_idex=i;
		}
	}

  将第一个活动选出来之后,就开始选下一个活动,下一个活动不比首个活动的特殊,他必须满足1,2两个条件。此时,开始思考,找出下一个活动后,我们是否就会开始进行重复的过程?即再找出符合1,2条件的下一个活动,一直找,一直找,直至找不出符合1,2条件的活动为止。

int arrange(int a[],int n)
{
	int i,k=0,min=a[1],min_idex=1,flag=1,j=1;
	while(flag==1)//flag用来标记是否能找到下一个符合条件的活动
   {	flag=0;//flag等于1时符合条件继续找出下一个活动,等于零时即循环结束,再找不到符合条件的活动。
	     k=0;
    	for(i=min_idex;i<n;i=i+2)
    	{
    		if(min>=a[i])
    		{
    			min=a[i];
    			min_idex=i;
    		}
    	}//找出首个活动(同时意味着满足第二个条件)
    	for(i=min_idex+1;i<n;i=i+2)//
    	{
    		if(a[i]>min)//能进入该if的数据代表符合第一个条件,即开始时间大于上一个活动的结束时间
    		{
    			flag=1;
    			a[k++]=a[i];
	    		a[k++]=a[i+1];//!!将找到符合条件1的数据放到数组a中去
    		}
    	}//
    	min_idex=1;
	    min=a[1];
    	n=k;//这三行就将下一次的准备工作做好了,接下来我来解释下这三行
    	if(flag==1)	j++;如果符合条件,能安排的活动数量加一
    }
return j;	
}

  其实找出第一个活动是,就意味着,我们将条件2的判断条件写出来了(应该能理解),然后我们想找下一个活动时,其实只要写出条件1的判断就好啦(我们想一下,找下一个活动满足条件1后,是不是可以直接掉头回去用判断首活动写出的条件2代码,来判断这个活动是否满足两个条件

  至于这三行代码,我们不是将符合条件的活动全都存到数组a中去了吗,但是要用这个数组我们还要进行初始化的准备工作,来让循环进行。其中:n=k,就将数组a的长度缩小至我们保存的符合条件1的所有活动了,其他两行作用和开始的min,min_idex作用一样。 

  到此为止,基本思路都差不多了,所以我先直接把通过oj的代码贴出来,再来说出我的辛酸经历。。

​
#include<stdio.h>
int arrange(int a[],int n);
void sort(int a[],int n);
int main()
{
	int i,g,m,n,a[20000];
	scanf("%d",&m);
	for(g=0;g<m;g++)
	{
		scanf("%d",&n);
		for(i=0;i<2*n;i++)
		scanf("%d",&a[i]);
		sort(a,2*n);
		printf("%d\n",arrange(a,2*n));
	}
	return 0;
}
void sort(int a[],int n)
{
	int i,j,k;
	for(i=0;i<n-2;i=i+2)
	{
		for(j=0;j<n-2-i;j=j+2)
		{
			if(a[j]>a[j+2])
			{
				k=a[j];
				a[j]=a[j+2];
				a[j+2]=k;
				k=a[j+1];
				a[j+1]=a[j+3];
				a[j+3]=k;
			}
		}
	}
}
int arrange(int a[],int n)
{
	int i,k=0,min=a[1],min_idex=1,flag=1,j=1;
	while(flag==1)
{	flag=0;
	k=0;
	for(i=min_idex;i<n;i=i+2)
	{
		if(min>=a[i])
		{
			min=a[i];
			min_idex=i;
		}
	}
	for(i=min_idex+1;i<n;i=i+2)
	{
		if(a[i]>min)
		{
			flag=1;
			a[k++]=a[i];
			a[k++]=a[i+1];
		}
	}
	min_idex=1;
	min=a[1];
	n=k;
	if(flag==1)	j++;
}
	return j;	
}
	/*
	1 10
	1 2
	4 7
	6 9
	9 11
	12 19
	13 18
	14 19
	13 40
	2 5
	3 6
	*/	
结果是 4

​

.  是不是感觉多了很多行。。。没错,这就是我前面说的有点小瑕疵的原因。。我他m以为oj里的测试数据是有序的,就是下一个活动的开始时间比上一个大,但没想到oj的测试数据是无序的。代码写完,我当时是真的不知道哪里错了,修修改改了一个小时都找不到哪里错了,最后想到是不是排序的问题后,又因为脑子昏了排序写错了,又改了半个小时才出来。。。。我真的无语子。。

  还有,写这题的上一个礼拜,我们学了递归,所以中途我想,哎哟,这题直接把两个判断条件写出来然后递归一手不久o了?

但我又他喵的没想到,oj的测试数据居然故意除了一组防止用递归的数据,来来的,写完之后时间直接超限。。

 这是代码(不要问为什么没有排序,当时还没考虑到乱序(;´༎ຶД༎ຶ`) )

#include<stdio.h>
int arrange(int a[],int n);
int main()
{
	int i,g,m,n,a[100];
	scanf("%d",&m);
	for(g=0;g<m;g++)
	{
		scanf("%d",&n);
		for(i=0;i<2*n;i++)
		scanf("%d",&a[i]);
		printf("%d",arrange(a,2*n));
	}
	return 0;
}
int arrange(int a[],int n)
{
	int i,k=0,b[100],min=a[1],min_idex=1,flag=0;
	for(i=1;i<n;i=i+2)
	{
		if(min>a[i])
		{
			min=a[i];
			min_idex=i;
		}
	}
	for(i=0;i<n;i=i+2)
	{
		if(a[i]>=min)
		{
			flag=1;
			b[k++]=a[i];
			b[k++]=a[i+1];
		}
	}
	if(flag==1)	return arrange(b,k)+1;
	return 1;
	
}

写这个题目太糟心啦,明天还要考四级,莱莱滴!!!!!!

当然啦,写这个题目我还是学会了很多的,至少我知道了这个会场安排是贪心算法的经典例题,哈哈哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值