厌殊

导航

《程序设计语言综合设计》第1周上机练习

7-8兼容任务

设有n个任务,其中每个任务有一个起始时间si和一个结束时间ei,且si<ei,同一时间只能完成一个任务。如果选择了任务i ,则它在时间区间 [si ,ei) 内占用资源。若区间 [si ,ei) 与区间 [sj, ej)不相交,则称任务 i 与任务 j 是相容的。那么,对于给定的任务时间区间,能互相兼容的最大任务个数是多少呢?

输入格式

第一行一个整数n (1<=n<=1000) ;
接下来n行,每行两个整数si 和 ei。

输出格式

互相兼容的最大任务个数

输入样例

4
1 3
4 6
2 5
1 7

输出样例

2

代码如下

#include <stdio.h>
int main(void)
{
	int n,i,j,k,m,min,count=1;
	scanf("%d",&n);
	struct Task{
		int s;
		int e;
	}t[1001];//定义一个存储时间区间的结构体
	for(i=0;i<n;i++)
	{
		scanf("%d %d",&t[i].s,&t[i].e);
	}
	for(i=0;i<n-1;i++)
	{
		for(j=i+1;j<n;j++)//冒泡排序法
		{
			if(t[i].e>t[j].e)//将时间区间的结束时间从小到大排序
			{
				k=t[i].e;
				t[i].e=t[j].e;
				t[j].e=k;
				m=t[i].s;
				t[i].s=t[j].s;
				t[j].s=m;
			}
		}
	}
	min=t[0].e;//将结束时间最小的时间区间的开始时间作为判断条件
	for(i=1;i<n;i++)
	{
		if(t[i].s>=min)
		{
                        count++;
			min=t[i].e;//取开始时间大于等于标记点的时间区间,将其结束时间作为新的标记点
		}
	}
	printf("%d\n",count);
	return 0;
}

贪心算法的应用,刚开始认为要按照开始时间排序,但是因为有相互包含的时间区间,不能得出最大任务个数。

7-9 顺序的分数

输入一个自然数 n,对于一个最简分数 a/b(分子和分母互质的分数),满足 1≤b≤n,0≤a/b≤1,请找出所有满足条件的分数,并按分数值递增的顺序输出这些分数。

输入格式

输入一个正整数 n(1≤n≤160)。

输出格式

每个分数单独占一行,按照分数值递增的顺序排列。

输入样例

5

输出样例

0/1
1/5
1/4
1/3
2/5
1/2
3/5
2/3
3/4
4/5
1/1

注:1、0 和任意自然数的最大公约数就是那个自然数。 2、互质指最大公约数等于1的两个自然数。

代码如下

#include <stdio.h>
int gy(int x,int y);//定义一个判断两个数是不是互质的函数,如果是则返回1,如果不是返回0
int main()
{
 int n,i,j,t,k,l,a,count=0;
 scanf("%d",&n);
 struct Fenshu{
  int m;
  int n;
  double sum;
 }f[30000];//定义一个存储互质数的结构体,n最大取值160,结构体的数组个数要足够大
 for(i=0;i<n;i++)
 {
  for(j=1;j<=n;j++)
  {
   if(i<=j)
   {
    a=gy(i,j);
    if(a==1){
     f[count].m=i;
     f[count].n=j;
     f[count].sum=i/(0.00001*j);//这里sum的精度要足够大,否则如果n很大,取舍的时候会得出相同结果
     count++;
    }    
   }
  }
 }
 for(j=0;j<count-1;j++)
 {
  for(i=0;i<count-1-j;i++)
  {
  if(f[i].sum>f[i+1].sum)//这里可以换用结构体整体交换的方法,代码长度会更少
  {
   t=f[i].sum;
   f[i].sum=f[i+1].sum;
   f[i+1].sum=t;
   k=f[i].m;
   f[i].m=f[i+1].m;
   f[i+1].m=k;
   l=f[i].n;
   f[i].n=f[i+1].n;
   f[i+1].n=l;
  }   
  }
 }
 for(i=0;i<count;i++)
 {
  printf("%d/%d\n",f[i].m,f[i].n);
 }
 return 0;
}
int gy(int x,int y)
{
 int z=0;
 int p;
 if(x!=0){
  while(p=x%y)//辗转相除法得出最大公约数
  {
   x=y;
   y=p;
  }  
 }
 if(y==1) z=1;
 return z;
}

这道题最大的问题在于sum的精度一直不够,在查询资料后用f[count].sum=i/(0.00001*j);,根据题目的需要和数据的大小,增减0的个数。
在看过同学的代码后,增加两种精度符合的方法
1.不先将sum求出,在冒泡排序判断大小时计算,将两式做比if((f[i].m*1.0/f[i].n)>f[i+1].m*1.0/f[i+1].n)
2.f[count].sum=(double)i/(double)j;

posted on 2022-03-05 10:20  厌殊  阅读(45)  评论(0)    收藏  举报