如何解决将特定数字相加的不同方法获得100
| 我想编写一个代码,说明一个人可以通过多种方式将5个不同的数字求和得到100。例如,数字为2,5,10,20,50
,并且可以重复任意次。 50+50
是一种方式,20+20+20+20+20
是一种方式。我不知道该如何编程。
我认为这应该通过递归函数来完成,并且我尝试编写一个实际上不知道如何写的函数,因此这是我想到的最好的方法:
#include<iostream>
#include<vector>
using namespace std;
int i,sum,n=5,counter=0;
int add(vector<int> &m){
if(m.size()==0) return 0 ;
for(i=0 ; i<m.size() ; i++ ){
sum=m[i]+add(m);
cout<< sum<<endl;
if(n>0) n--;
m.resize(n);
}
}
int _tmain(int argc,_TCHAR* argv[])
{
int i,n=5;
vector<int> m;
m.resize(5);
m[0]=2;
m[1]=5;
m[2]=10;
m[3]=20;
m[4]=50;
add(m);
return 0;
}
解决方法
只是为了好玩
#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
#include <algorithm>
static const int terms[] = { 2,5,10,20,50,/*end marker*/0 };
using namespace std;
typedef vector <int> Solution;
typedef vector <Solution> Solutions;
inline int Sum(const Solution& s)
{
return accumulate(s.begin(),s.end(),0);
}
template <typename OutIt>
OutIt generate(const int target,const int* term,Solution partial,OutIt out)
{
const int cumulative = Sum(partial); // TODO optimize
if (cumulative>target)
return out; // bail out,target exceeded
if (cumulative == target)
{
(*out++) = partial; // report found solution
return out;
} else
{
// target not reached yet,try all terms in succession
for (; *term && cumulative+*term<=target; term++)
{
partial.push_back(*term);
out = generate(target,term,partial,out); // recursively generate till target reached
partial.pop_back();
}
return out;
}
}
Solutions generate(const int target)
{
Solutions s;
generate(target,terms,Solution(),back_inserter(s));
return s;
}
void Dump(const Solution& solution)
{
std::copy(solution.begin(),solution.end(),std::ostream_iterator<int>(std::cout,\" \"));
std::cout << std::endl;
}
#ifdef _TCHAR
int _tmain(int argc,_TCHAR* argv[])
#else
int main(int argc,char* argv[])
#endif
{
Solutions all = generate(100);
for_each(all.rbegin(),all.rend(),&Dump);
return 0;
}
$ 0.02
为了真正回答这个问题,我删除了所有不需要的解决方案输出,从而极大地优化了代码。现在它的效率要高得多(我以target=2000
的速度将其基准速度提高了25倍),但仍无法扩展到large6ѭ的大范围...
#include <iostream>
#include <vector>
using namespace std;
size_t generate(const int target,vector<int> terms)
{
size_t count = 0;
if (terms.back()<=target)
{
int largest = terms.back();
terms.pop_back();
int remain = target % largest;
if (!remain)
count += 1;
if (!terms.empty())
for (; remain<=target; remain+=largest)
count += generate(remain,terms);
}
return count;
}
int main(int argc,char* argv[])
{
static const int terms[] = {2,50};
std::cout << \"Found: \" << generate(1000,vector<int>(terms,terms+5)) << std::endl;
return 0;
}
希望更智能的模运算能开始反映PengOne关于解决此问题的建议。
, 从理论上讲,可以使用生成函数解决此问题。生成函数不是函数,也不生成任何东西(好名字,是吗?),但是它确实很好地跟踪了信息。结果是您的问题的答案是在扩展时,路数等于x^100
的系数。
1/(1-x^2) * 1/(1-x^5) * 1/(1-x^10) * 1/(1-x^20) * 1/(1-x^50)
这是为什么的解释。回想一下ѭ10。这是我们将用来解决问题的基本生成函数。
假设您有数字A,B,...,N(在您的示例中为2,50),您可以重复任意次。然后考虑(生成)功能
f(x) = 1/(1-x^A) * 1/(1-x^B) * ... * 1/(1-x^N)
f(x)
中的x^M
系数是将M
写成形式的总和的方式数目
M = a*A + b*B + ... + n*N
其中a,b,...,n
是非负整数。
为什么这样做?因为扩展f(x)
中的任何单项式项都来自1/(1-x^A)
中的一个项,对于某些非负a
,它看起来像x^(a*A)
,其他项也类似。由于指数相加,因此ѭ12的系数就是写出这样一个sum 14的总和。
我知道这不是编程的答案,但希望您可以使用该想法编写程序。
, 这是一个递归解决方案:http://ideone.com/ip98M
#include <iostream>
template<size_t N>
void find_combinations_helper(int total,const int (&denoms)[N],int denoms_used,int remaining,int (&counts)[N])
{
if (remaining == 0) {
int partial_sum = 0;
for( int i = 0; i < denoms_used; ++i ) {
if (counts[i]) {
std::cout << counts[i] << \"*\" << denoms[i];
partial_sum += counts[i] * denoms[i];
if (partial_sum < total) std::cout << \" + \";
}
}
std::cout << \"\\n\";
return;
}
if (denoms_used == N) return;
for( counts[denoms_used] = 0; remaining >= 0; (remaining -= denoms[denoms_used]),++counts[denoms_used] )
find_combinations_helper(total,denoms,denoms_used + 1,remaining,counts);
}
template<size_t N>
void find_combinations( int total,const int (&denoms)[N] )
{
int solutions[N];
find_combinations_helper(total,total,solutions);
}
int main(void) {
const int bill_denoms[] = { 50,2 };
find_combinations(100,bill_denoms);
}
, 这看起来不正确:
m[0]=2;
...
m[0]=50;
不应该是m [4] = 50;吗?
编辑
您永远不会声明值100,如何知道何时达到100?
, 您现在使用的函数add
的代码将使您产生堆栈溢出:)因为您在修改向量m
之前先对add(m)
进行了递归调用。因此,add
总是以未经修改的向量被调用,并且基本情况永远不会受到打击。
我不知道我是否掌握了您想做的事,但是:
#include <iostream>
#include <sstream>
#include <vector>
void add(int i,std::string s,int sum)
{
if (sum == 100)
{
std::cout << s << \"=100\" << std::endl;
return;
}
if (sum > 100)
{
return;
}
if (sum < 100)
{
std::ostringstream oss;
oss << s << \"+\" << i;
add(i,oss.str(),sum+i);
}
}
int main()
{
std::vector<int> m;
m.resize(5);
m[0]=2;
m[1]=5;
m[2]=10;
m[3]=20;
m[4]=50;
// This loop will initiate m.size lines of recursive calls
// one for each element of the array
for (size_t i = 0; i < m.size(); i++)
{
add(m[i],\"\",0);
}
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。