百度笔试编程题-加油站和代金券

题目描述:

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

输入

该函数方法的输入包括五个参数:

distance,一个整数,表示始发城市和目的地域市之间的距离
coupontypes,一个整数,表示代金券的种类(M
ouponvalues,一个整数列表,表示代金券的价值
tols,一个整数,表示始发城市和目的地城市之间的收要站数量(N)
tollDistances,一个整数列表,表示收费站距始发城市的距高

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

输出

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

约束条件

0≤distance≤10e4;
0≤couponTypes≤100
0≤couponvalues[i]≤10e5
0≤i<couponTypes
0≤tolls≤10e3
0≤tollDistances[j]≤ tollDistances[j+1]≤distance
0≤ j≤ tolls

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

输入

distance =10
coupontypes=4
couponvalues=[1 2 5 10]
tolls=3
tollsDistances=[0 5 10];(我的代码默认了这里0位置都有加油站)

输出

16

代码与分析

直接思路(递归求解)

将其分解成子问题求解,子问题:每两个加油站间距离对应代金券的组合方式(即从可选的方式中挑选出和为定值方式组合)

#include<list>  
#include<iostream>
#include<vector>
using namespace std;  
static int count;
list<int>list1;  
vector<int>couponValues;
vector<int>tollDistance;
void methods_nums(int sum, int n)   
{  
    // 递归出口  
    if(n < 0 || sum <= 0)  
        return;  
    // 输出找到的结果  
    if(sum == n)  
    {  
        // 反转list  
        list1.reverse();  
        for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++)  
            cout << *iter << " + ";  //输出每一种的组合方式,可以注释不要
        cout << n << endl;  
        count++;
        list1.reverse();      
    }  
    list1.push_front(couponValues[n-1]);      //01背包问题  
    methods_nums(sum-couponValues[n-1], n);   //放n,n-1个数填满sum-n 
    list1.pop_front();  
    methods_nums(sum, n-1);     //不放n,n-1个数填满sum   
}  
int nums( int distance,int couponTypes,vector<int>couponValues,int tolls,vector<int>tollDistance)
{
   int result=1;
   for(int i=0;i<tolls-1;i++)
   {
    count=0;
    methods_nums((tollDistance[i+1]-tollDistance[i]),couponTypes);
    result=result*count;
   }
   cout<<result<<endl;
   return result;
}
int main()  
{  
    int distance;
    int couponTypes;
    int tolls;  
    cout << "distance" << endl;  
    cin >> distance;  
    cout << "couponTypes" << endl;  
    cin >> couponTypes;  
    cout << "couponValues" << endl;  
    couponValues.resize(couponTypes);
    for (int i = 0; i < couponTypes; i++)
    {
        cin >> couponValues[i];
    }
    cout << "tolls" << endl;  
    cin >> tolls;  
    cout << "tollDistance" << endl;  
    tollDistance.resize(tolls);
     for (int i = 0; i < tolls; i++)
    {
        cin >> tollDistance[i];
    } 
    nums(distance,couponTypes,couponValues,tolls,tollDistance);  
    return 0;  
}

剪枝二叉树求解方法: