版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29567701/article/details/79829274
题目:来源于腾讯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;
}