有四种不一样的分子,a,b是单原子分子,c,d是双原子分子。给出构成这四种分子的原子质量。用这四种分子构成一个元素,给定元素质量,求最多能够用多少个分子。ios
思路:其实机器解题和人解题是一个思路,遇到这种问题,人怎么解决呢。就是尝试。算法
这里有两个算法思想:动态规划和贪心算法。编程
动态规划:将问题分部分解决,且最好前面被解决的问题可以被后面屡次使用,那就把前面解决了的问题结果存起来,以备后面使用,从而提升效率。spa
贪心算法:每次先试最有可能出现解的路径。PS;事实上,我在生活中很是不会使用贪心算法。好比去找一本书,命名以为最有可能在第三层,确要从第一层找起,这样作事效率就低。改正之~编程反过来能启发生说。code
这个问题能够写为f(a,b,c,d,x)排序
a,b,c,d分别为四种分子的质量,x为待合成的化合物的质量。递归
那么f(a,b,c,d,x) = f(a,b,c,d,x - a) + 1 或者=f(a,b,c,d,x - b) + 1 或者=f(a,b,c,d,x - c) + 1 或者=f(a,b,c,d,x - d) + 1 hash
那么f(a,b,c,d,x - b)是否是也能够按照以上方法分解了呢,直到最后发现x为0了,那么恭喜,试出来一个,若是小于0了,那不行,得从新试。it
聪明的你应该发现,递归就能够解决问题io
以上就是遍历,若是用一个全局变量记录结果,会知道最大会返回多少,那就是解。
可是咱们用贪心,先将,a,b,c,d进行排序,先对质量小的进行递归,那么,是否是第一个被试出来来的,就是解呢。这样计算量就会大大下降。
若是这个题改为最多能有多少个原子,会复杂一点,由于要创建分子质量和原子数(或者原子质量)之间的hash表,用multimap就能够解决。这样作的目的是为了可以排序,实现贪心。
注意:不能用map,由于不容许键值相同的元素出现。
下面贴出最多原子数的代码:
#include <iostream> #include<map> using namespace std; int funCore(multimap<int,int> &m ,int massX); int fun(int massA,int massB,int massC,int massD ,int massX); int main() { //int res = fun(5,8,5,3,23); map<int,int> m; m.insert(make_pair(1,1)); m.insert(make_pair(1,2)); int res = fun(5,8,5,3,23); cout << res; return 0; } //summary:生成可用的hashmap,以单原子质量为键值,分子质量为value //parameters: //massA:原子A的质量 //massA:原子B的质量 //massA:原子C的质量 //massA:原子D的质量 //massX;待构成元素的质量 //return:最多的原子数。 int fun(int massA,int massB,int massC,int massD ,int massX){ multimap<int,int> numMap; numMap.insert(make_pair(massA,massA)); numMap.insert(make_pair(massB,massB)); numMap.insert(make_pair(massC,massC * 2)); numMap.insert(make_pair(massD,massD * 2)); return funCore(numMap,massX); } //summary:递归计算最多原子数。算法思想是,动态规划,就是将问题先解决一部分,并把结果存储下来。递归提供了存储的手段 //具体就是funCore(multimap<int,int> &m ,int massX) = 选一个分子*单分子原子数 + funCore(multimap<int,int> &m ,int massX - 选择的分子数量) //还有一个算法思想是,贪心算法,先选原子质量小的分子,multimap可以对元素按键值进行从小到大排序,注意不能用map,map不容许键值重复 int funCore(multimap<int,int> &m ,int massX){ if(massX == 0) return 0; if(massX < 0) return -1; for(multimap<int,int>::iterator it=m.begin();it!=m.end();++it){ int nA = funCore(m,massX - it->second); if(nA >= 0) return nA + it->second / it->first; } return -1; }