数据结构:组装齿轮问题

题目:


背景

你的弟弟买了一套新的玩具,用这套玩具,他可以组装自己的机器。在玩具中有很多不同尺寸的齿轮,开始的时候他可以直接使用齿轮组装不同转速比

的传动装置,但后来他发现有些转速比用已有的齿轮就很难组装出来。他希望你给他编写一个电脑程序,帮助他找到组装传动装置的方法。

譬如,在这个玩具中包含了 6 齿、12 齿和 30 齿的齿轮,而你的弟弟希望搞一个转速比为 5:4 的传动装置。下图就显示了一种可能的方案:

这个传动方案使用了四个齿轮,第一跟轴上是 30 齿和 12 齿的,第二跟轴上是 6 齿和 12 齿的。转速比可以通过如下公式获得:

(30 / 12) * (6 / 12) = (5 / 2) * (1 / 2) = 5 / 4 = 5:4

然而,使用以上三种齿轮,就没法组装出转速比为 1:6 的传动装置。

题目

给定齿轮的大小(齿轮有多少个齿),判断通过这些齿轮能否组成一定的转速比。我们假定每种齿轮的数量都足够多。

输入

输入的第一行是一个数字 n,它表示在玩具中有几种齿轮(1 <= n <= 20)。下一行包含了 n 个数字 c1...cn,以空白符隔开,他们表示了玩具中的

 n 种齿轮的大小(5 <= ci <= 100,其中 1 <= i <= n)。你可以假定在玩具中所有齿轮的大小都是最小齿轮大小的倍数。

再下一行有一个整数 m,它表示所需的实现的转速比有多少组,而之后的 m 行中每行都有两个整数 a 和 b,它们表示要实现的转速比为 a:b,其中

 1 <= a, b <= 10000。

  测试输入 期待的输出 时间限制 内存限制 额外进程
测试用例 1 以文本方式显示
  1. 3↵
  2. 6 12 30↵
  3. 2↵
  4. 5 4↵
  5. 1 6↵
以文本方式显示
  1. Gear ratio 5:4 can be realized.↵
  2. Gear ratio 1:6 cannot be realized.↵
1秒 1024KB 0
测试用例 2 以文本方式显示
  1. 1↵
  2. 42↵
  3. 2↵
  4. 13 13↵
  5. 42 1↵
以文本方式显示
  1. Gear ratio 13:13 can be realized.↵
  2. Gear ratio 42:1 cannot be realized.↵
1秒 1024KB 0

思路:

这道题的本质其实是利用现有的齿轮齿数与最小齿数的比值,来作为因子,通过乘法或者除法,最后得到目标的比值的分子/分母。一般的做法就是把简化后的齿数相乘,通过大量的得到乘积,同时对目标比例的分子分母同时扩大n倍(分子分母扩大相同的倍数比值不变),测试扩大后的分子分母,是否在之前得到的乘积中出现过。
伪代码:
define num 100000

用每个数除以最小齿数(每个齿轮齿数都是最小齿数的整倍数),得到结果加到a[num]中,得到k个数。

同时用b[num]记录a[num]中出现的数。x出现过则b[x]置为1

//这一步可以先排序,再用后面的数除以第一个,也可以直接让每个数两两相除,如果余数是0而且商不为0,再加到a[num]中

for i 0到k // k是指当前a[num]中的数的个数,在下面的循环中也会改变k值

for j 0到k

if a[j]=0

continue //跳出这次循环,但是要继续

if a[i]%a[j]=0 //一开始我怀疑这个if 存在的意义,但是去掉这个if后最后一个用例无法通过

temp=a[i]/a[j]

if temp=0

continue //temp是0就没有意义了

if b[temp]不为1

temp加入a[num] //同时k++

b[temp]置为1

temp=a[i]*a[j] //temp如果是int型似乎会溢出

if temp>100000或者temp=0 //这个题目的测试用例是有限的,否则这个算法就是大失败

continue

else

if b[temp]不为1

temp加入a[num] //k++

b[temp]置为1

//完毕

看到上面的代码就是这个程序的核心部分——乘法。有了这个步骤以后,就可以在目标比例的分子分母中同时扩大n(n>1)倍时,测试在b[num]中是否为1(当然只要测试到100000)

代码:

#include 
#include 
#include 
#include 
#define N 100000
/*...........................
算法分析:
1、首先遍历所有齿轮,求出齿轮与最小齿轮之间的倍数,并用一个数组record记录是否出现过这个倍数
2、倍数之间如果出现了新的倍数关系,加进去
3、进行乘法关系,乘法得到的结果小于一给定值
4、进行匹配,看分子分母是否出现过5、BIT的同学们请不要直接Copy代码,否则后果不堪设想~~~~
.............................*/

static unsigned long number[N];  //对倍数的储存
int mark[N];   //记录是否出现过

int cmp(const void *a,const void *b)
{
	return *(long *)a- *(long *)b;
}

void Init()  //初始化
{
	int k=0;
	memset(number,0,sizeof(number));
	memset(mark,0,sizeof(mark));
	int n;  //齿轮
	static unsigned long temp[30];
	scanf("%d",&n);
	int i,j,min=50000;
	for(i=0;i N||tep == 0)  continue;//超出和为零没意义
			else
			{
				if(mark[tep-1]!=1)
				{					
					number[k++]=tep;
					mark[tep-1]=1;
				}
			}
		}
	}
	return;
}

long GCD(long a, long b)   //求最大公约数,化简,以免错过倍数
{
	long temp;
	temp=a>b?a:b;
	b=aN||tep_b>N) break;
			if(mark[tep_a-1]==1&&mark[tep_b-1]==1)
			{
				flag=1;
				break;
			}
			n++;
		}
		if(flag==0)  
			printf("Gear ratio %ld:%ld cannot be realized.\n",mya,myb);  
		else  
			printf("Gear ratio %ld:%ld can be realized.\n",mya,myb);  
	}
	return 0;
}




你可能感兴趣的:(School)