加油站优惠券组合方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27022241/article/details/82561371

                                    加油站优惠券组合方式

题目描述

    奥斯汀需要从他所在的城市去另一座城市,他所在城市和目的城市之间有N个收费站。奥斯汀有M种代金券,价值各不相同,他可以在收费站使用,以便继续走到下一个收费站。他有无限量的各种代金券。要从一个收费站走到另一个收费站,他必须交纳一组价值等于收费站距离的代金券。例如,如果他有价值3和2的代金券,且他需要在距离为26个单位的收费站之间行进,则他将交纳8个价值为3的代金券和一个价值为2的代金券。

    奥斯汀想知道:从始发城市到目的城市,他可以有多少种交纳不同组代金券的方式。

    写一个算法:帮助奥斯汀找出他从始发城市到目的地城市可交纳不同组代金券的方式数目。

输入

    该函数方法的输入包含5个参数:

    distance,一个整数,表示始发城市和目的地城市之间的距离;

    couponTypes,一个整数,表示代金券的种类(M);

    couponValues,一个整数列表,表示代金券的价值;

    toils,一个整数,表示始发城市和目的城市之间的收费站数量(N);

    toilDistance,一个整数列表,表示收费站距始发城市的距离。

输出

     返回一个整数,表示它从始发城市到目的地城市可以交纳不同组合代金券的方式数目。

约束条件

    0<=distance<10^4

    0<couponTypes<100

    0<couponValues[i]<10^5

    0<=i<couponTypes

    0<toils<10^3

    0<toilDistance[j]<toilDistance[j+1]<=distance

    0<=j<toils

注意
    输出应为10*9+7的取模运算

示例

    输入:

    distance=10

    couponTypes=4

    couponValues=[1,2,5,10]

    toils=3

    toilDistances=[0,5,10]

    输出:

    16

    解释:

    三个收费站在距离始发地点0、5、10处。

    第一个收费站在距离0处,所以不需要存入任何代金券,所以,方式数目是1。

    第二个收费站在距离第一个收费站5个单位处,可能的4组代金券是{1,1,1,1,1},{1,1,1,2},{1,2,2},{5},即4种方式。

    第三个收费站与第二个收费站距离为5个单位。可能的4组代金券是{1,1,1,1,1},{1,1,1,2},{1,2,2},{5},即4种方式。

    因此,可能的组合数是1*4*4=16。

    所以输出是16。

代码

#include <iostream>
#include <string>
#include <cmath>
#include <vector>

using namespace std;

int couponCombinations(int distance, int couponTypes, int* couponValues, int toils, int* toilDistances)
{
	
	vector<int> resDis;
	int i, j, k, p, q;
	resDis.push_back(toilDistances[0]);
	for (i = 0; i < toils-1; i++)
		resDis.push_back(toilDistances[i + 1] - toilDistances[i]);
	int result = 1;
	for (j = 0; j < toils; j++)
	{
		vector<vector<int>> dp(couponTypes+1);
		int res = resDis[j];
		for (k = 0; k <=couponTypes; k++)
			dp[k].resize(res+1);
		for (p = 0; p <=couponTypes; p++)
		{
			for (q = 0; q <=res; q++)
			{
				dp[p][q] = 0;
			}
		}
		for (k = 0; k <=couponTypes; k++)
		{
			dp[k][0] = 1;
		}
		for (p = 1; p <=couponTypes; p++)
		{
			for (q = 1; q <=res; q++)
			{
				dp[p][q] = 0;
				for (k = 0; k <= q / couponValues[p - 1]; ++k)
				{
					dp[p][q] += dp[p - 1][q - k * couponValues[p - 1]];
				}
			}
		}
		result *= dp[couponTypes][res];
		dp.clear();
	}
	return result;

}


int main()
{
	int distance, couponTypes, toils;
	distance = 10;
	couponTypes = 4;
	toils = 3;
	int couponValues[4] = {1,2,5,10};
	int toilDistances[3] = { 0,5,10};
	int result = couponCombinations(distance, couponTypes, couponValues, toils, toilDistances);

	cout << "组合数共:" << result << "种\n";
	system("pause");
	return 0;

}

PS:参考 硬币面值组合问题

猜你喜欢

转载自blog.csdn.net/qq_27022241/article/details/82561371