嗯哼,別人問的問題,看的我也頭暈,百度了一下動態規劃,看了看才想起來該怎麼做,今天寫了寫代碼,實現了~
要求是遞歸,動態規劃,想了想這種方法也是最簡單的~
所謂動態規劃:把多階段過程轉化為一系列單階段問題,利用各階段之間的關系,逐個求解。動態規劃算法通常用於求解具有某種最優性質的問題。在這類問題中,可能會有許多可行解。每一個解都對應於一個值,我們希望找到具有最優值的解。動態規劃算法與分治法類似,其基本思想也是將待求解問題分解成若干個子問題,先求解子問題,然後從這些子問題的解得到原問題的解。與分治法不同的是,適合於用動態規劃求解的問題,經分解得到子問題往往不是互相獨立的。若用分治法來解這類問題,則分解得到的子問題數目太多,有些子問題被重復計算了很多次。如果我們能夠保存已解決的子問題的答案,而在需要時再找出已求得的答案,這樣就可以避免大量的重復計算,節省時間。我們可以用一個表來記錄所有已解的子問題的答案。不管該子問題以後是否被用到,只要它被計算過,就將其結果填入表中。這就是動態規劃法的基本思路。(摘自百科)(時間復雜度為一個多項式的復雜度)
背包問題(Knapsack problem)是一種組合優化的NP完全問題。問題可以描述為:給定一組物品,每種物品都有自己的重量和價格,在限定的總重量內,我們如何選擇,才能使得物品的總價格最高。問題的名稱來源於如何選擇最合適的物品放置於給定背包中。
題目如截圖:
解題思路:
n代表面值
n為1,直接看是否可以整除;
n>1,看在沒有第n個面值的時候多少,然後看有1個、2個....j/n個面值為n的時候需要幾枚硬幣,取最小值
將這些直接存在數組中,然後去數組裡的最小值
代碼:
1 #include"header_file.h" 2 using namespace std; 3 4 int coin_num(vector<int> T,int i,int j) 5 { 6 if(i==1) 7 { 8 if(j%T[0]==0) 9 { 10 return j/T[0]; 11 } 12 else 13 { 14 return 9999; 15 } 16 } 17 else 18 { 19 int min; 20 min=coin_num(T,i-1,j); 21 int temp; 22 temp=j/T[i-1]; 23 for(int m=0;m<=temp;m++) 24 { 25 if(min>(m+coin_num(T,i-1,j-m*T[i-1]))) 26 min=m+coin_num(T,i-1,j-m*T[i-1]); 27 28 } 29 return min; 30 } 31 } 32 33 vector<int> all_num(vector<int> T,int j) 34 { 35 vector<int> v; 36 for(int i=0;i<T.size();i++) 37 v.push_back(coin_num(T,i+1,j)); 38 // for(int i=0;i<T.size();i++) //use for test 39 // cout<<v[i]<<" "; 40 //v.push_back(coin_num(T,i+1,j)); 41 return v; 42 } 43 44 int find_min(vector<int> v) 45 { 46 int min=0; 47 for(int i=1;i<v.size();i++) 48 { 49 if(v[min]>v[i]) 50 min=i; 51 } 52 return v[min]; 53 } 54 55 int main(void) 56 { 57 int n; 58 cout<<"input n:"; 59 cin>>n; 60 61 vector<int> T; 62 for(int i=0;i<n;i++) 63 { 64 int temp; 65 cin>>temp; 66 T.push_back(temp); 67 } 68 69 int j; 70 cout<<"input j:"; 71 cin>>j; 72 73 vector<int> v; 74 v=all_num(T,j); 75 int min; 76 min=find_min(v); 77 cout<<"min:"<<min<<endl; 78 }