中兴2018校招笔试题目 之 整数分解

题目:

小明要从A地走到B地,途中会路过若干个收费站,每经过一个收费站就要缴纳一定数量的道路券,缴纳的道路券等于走过的路程。道路券有不同的规格,在每个收费站缴纳的道路券可以是各种规格的组合,各种规格道路券的数量没有限制。给定道路券的规格,以及各收费站之间的距离,求总共有多少种缴纳道路券的方式。

例:

4种道路券,规格分别为:1, 2, 5, 10。

3个收费站,与起点之间的距离依次为:0, 5, 10。

则共有16种缴纳方式。

解释:

在第一个收费站不用缴纳;在第二个收费站要缴纳价值为5的收费券,有四种可选组合:(1, 1, 1, 1, 1), (1, 1, 1, 2), (1, 2, 2),(5);在第三个收费站也要缴纳价值为5的收费券,也是4种组合。因此,共有4×4=16种缴纳方式。

算法思路:

这实际是一个整数分解问题,只不过是需要用给定的几个整数来对一个整数进行分解。可以采用递归的方式(以5为例):

第一个因子设为1,5 - 1 = 4,接下来对 4 进行分解。

扫描二维码关注公众号,回复: 3100230 查看本文章

第一个因子设为2,5 - 2 = 3,接下来对 3 进行分解。

......

递归的终止条件是:分解完毕或者无法继续分解。

这里要注意的是,(1, 1, 1, 2) 和 (1, 2, 1, 1)是同一个分解,因此,递归的过程中,比当前因子小的因子舍弃不用。例如,已经选择的因子是(1, 2),则下一个因子只从2、5、10里选,不再选择1。

代码:

#include <vector>
#include <iostream>

using namespace std;

int couponType;			            // 道路券规格种类
vector<int> couponValues;			// 各种规格的值
int tollNum;			            // 收费站数量
vector<int> tollDistance;		    // 各收费站与起点的距离

//
// val:	要分解的整数
// start: 从第几个coupon开始
//
int choose(int val, int start)
{
	int cnt = 0;
	for (int i = start; i < couponType; i++)
	{
		val -= couponValues[i];	    // 以第i个coupon作为因子
		if (val == 0)				// 分解完毕
			cnt++;
		else if (val > 0)			// 未分解完
		{
			cnt += choose(val, i);	// 继续分解,注意第二个参数
		}
		val += couponValues[i];		// 还原val的值
	}
	return cnt;
}

void main()
{
	// 输入例子
	couponType = 4;
	int values[] = { 1, 2, 5, 10 };
	couponValues.assign(values, values + couponType);
	tollNum = 3;
	int dis[] = { 0, 5, 10 };
	tollDistance.assign(dis, dis + tollNum);

	int cnt = 1;				    // 缴纳方式数目
	for (int i = 1; i < tollNum; i++)    // 遍历每个收费站
	{
		int dis = tollDistance[i] - tollDistance[i - 1];			
		cnt *= choose(dis, 0);
	}

	cout << cnt<< endl;
	cin.get();
}

猜你喜欢

转载自blog.csdn.net/csdnqixiaoxin/article/details/82470226