有四種不一樣的分子,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; }