腾讯2018暑期实习第2题 从几首特定长度的歌曲中求指定长度歌曲的组合

1 篇文章 0 订阅
1 篇文章 0 订阅

题目:来源于腾讯2018实习第2题
从几首特定长度的歌曲中求指定长度歌曲的组合
其实该题目就是“求一个数组里面所有和等于m的组合”的一个变种。

"X首长度为A的歌,Y首长度为B的歌," 中挑出 长度为a 的歌,
共有多少种组合;不用管挑选的顺序

先上代码:

#include<iostream>  
#include<vector>
using namespace std;

//a:存放待操作的数据 
//start:每个子问题从数组a的什么位置开始  
//*path:临时数组 记录每一条走过的路径     
//top: path的下标   
//sum:最终结果 求一个数组里面所有和等于m的组合
//num:返回 总共得到的组合种类的数目
//v:返回满足和等于m的所有排列的组合 到二维数组 vector<vector<int>> v 中
void findpath(vector<int> a, int start, int * path, int top, int sum, int &num)
{
    for (int i = start; i<a.size(); i++)
    {
        sum -= a[i];//想法是做减法
        path[top++] = i;//path记录每一条经过的路径  
        if (sum == 0)
            num++;//得到的组合种类的数目 +1
        else if (sum > 0)
            findpath(a, i + 1, path, top, sum, num);//迭代
        sum += a[i];
        top--;
    }
}

int main()
{
    vector<int>  v;

    int a;
    int A, X, B, Y;
    cin >> a;
    cin >> A >> X >> B >> Y;

    for (int i = 0; i < X; ++i)
        v.push_back(A);
    for (int i = X; i < X + Y; ++i)
        v.push_back(B);

    int path[6] = { 0 };
    int No = 0;//总共得到的组合种类的数目

    findpath(v, 0, path, 0, a, No);
    cout << No << endl;

    return 0;
}

其中,核心子函数
void findpath(vector a, int start, int * path, int top, int sum, int &num);
来源于这篇博文
只做了小小的改动。
至于主函数的输入输出,一目了然,不用多加解释啦。

如果想要显示具体的组合数,则需要在findpath()子函数中多加一个
带引用的二维可变成数组

vector<vector<int>> &v

来存储,即:

void findpath(vector<int> a, int start, int * path, int top, int sum, vector<vector<int>> &v)

具体代码如下:

//Copyright @东篱_

#include<iostream>  
#include<vector>
using namespace std;

//v:返回满足和等于m的所有排列的组合 到二维数组 vector<vector<int>> v 中
void findpath(vector<int> a, int start, int * path, int top, int sum, vector<vector<int>> &v)
{
    vector<int> v1;
    for (int i = start; i<a.size(); i++)
    {
        sum -= a[i];//想法是做减法
        path[top++] = i;//path记录每一条经过的路径  
        if (sum == 0)
        {
            for (int j = 0; j<top; j++)
                v1.push_back(a[path[j]]);//将组合中的每一个数压入到v1中
            v.push_back(v1);//再将v1压入到v中
            vector<int>().swap(v1);//删掉之前v1保存过的数据及占用的空间
        }
        else if (sum > 0)
            findpath(a, i + 1, path, top, sum, v);
        sum += a[i];
        top--;
    }
}

void disp(vector<vector<int>> v)
{
    for (auto &r : v)
    {
        for (auto c : r)
            cout << c << " ";
        cout << endl;
    }
}

int main()
{
    vector<int>  v;

    int a;
    int A, X, B, Y;
    cin >> A >> X >> B >> Y;

    for (int i = 0; i < X; ++i)
        v.push_back(A);
    for (int i = X; i < X + Y; ++i)
        v.push_back(B);
    for (auto c : v)
        cout << c << " ";
    cout << endl;

    int path[6] = { 0 };
    vector<vector<int>> vv;
    cout << "请输入 所求组合数之和:" << endl;
    while (cin >> a)
    {
        findpath(v, 0, path, 0, a, vv);
        cout << "共有 " << vv.size() << " 种组合 里面所有数字之和 =" << a << endl;
        cout << "得到的组合如下:" << endl;
        disp(vv);
        vector<vector<int>>().swap(vv);//删掉上一次测试保存下来的所有组合数数据
        cout << "请输入 所求组合数之和:" << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值