1. 程式人生 > >動態規劃——砝碼稱重

動態規劃——砝碼稱重

問題描述:

設有1g,2g,3g,5g,10g,20g的砝碼各若干枚(其總重≤1000g),要求:

輸入:

a1   a2   a3   a4   a5   a6(表示1g砝碼有a1個,2g砝碼有a2個,......20g砝碼有a6個)

輸出:

Total=N (N表示用這些砝碼能稱出的不同重量的個數,但不包括一個砝碼也不用的情況)

輸入樣例:1  1  0   0   0   0

輸出樣例:Total=3,表示可以稱出1g,2g,3g三種不同的重量

動態規劃求解:

從砝碼1開始分析,假設前i個砝碼能稱出的不同重量為Q[i],那麼Q[i]一定是這樣計算出來的:在Q[i-1]的基礎上,對Q[i-1]個不同的重量,分別新增k個砝碼i,再新增的過程中除去重複情況。

假設:w[N]表示N個不同重量的砝碼(例子中N=6),w[0~N-1]。

      c[N]表示N個不同砝碼相應的數量,c[1~N]。

則:Q[i] = (Q[i-1] + k*w[i])-新增過程中重複的個數。其中0=<k<=c[i]。

定義一個輔助布林型陣列visit[M+1],這裡的M是例子中的1000,表示最大重量不超過M。

visit[j]=1表示,重量為j的情況已經存在,否則表示重量為j的情況還未出現。其中visit[0]作為一個多餘空間存在,可以作為一個臨時變數。最後遍歷visit[1~M],統計1的個數就得到不同重量的個數。

通過這個輔助陣列,就可以除去重複情況,實現如下:

  1. 1 #include <iostream>  
  2.  2 using namespace std;  
  3.  3 #define N 6  
  4.  4 #define M 1000  
  5.  5 int w[N]={1,2,3,5,10,20};  
  6.  6 int c[N]={0};  
  7.  7 int visit[M+1] = {0};  
  8.  8   
  9.  9 int weight_count()  
  10. 10 {  
  11. 11         int i = 0;  
  12. 12         int j = 0;  
  13. 13         int total = 0;  
  14. 14         int count =0;  
  15. 15   
  16. 16         visit[0] = w[0]*c[0];//visit[0]用於每新增一個砝碼時遍歷的結束位置
      
  17. 17         for(i = 1;i<=c[0];i++)  
  18. 18                 visit[w[0]*i] = 1;//初始化visit[1~c[0]],表示已經添加了砝碼1  
  19. 19         for(i = 1;i<N;i++)  
  20. 20         {  
  21. 21                 int m = visit[0];  
  22. 22                 for(int k = 1;k<=c[i];k++)  
  23. 23                 {  
  24. 24                         for(j = 0;j<=m;j++)  
  25. 25                         {  
  26. 26                                 if(j+ k*w[i]>M)  
  27. 27                                         break;  
  28. 28                                  if(visit[j] == 1 && visit[j + k*w[i]] != 1 || j==0)  
  29. 29                                  {  
  30. 30                                         visit[j + k*w[i]] = 1;  
  31. 31                                         total = j+k*w[i];  
  32. 32                                  }  
  33. 33                         }  
  34. 34                 }  
  35. 35                 visit[0] = total;  
  36. 36         }  
  37. 37         for(i = 1;i<=M;i++)  
  38. 38         {  
  39. 39                 if(visit[i]==1)  
  40. 40                 {  
  41. 41                         cout << i << " ";  
  42. 42                         count ++;  
  43. 43                 }  
  44. 44         }  
  45. 45         return count;  
  46. 46   
  47. 47 }  
  48. 48 int main()  
  49. 49 {  
  50. 50         int i = 0;  
  51. 51         for(i = 0;i<N;i++)  
  52. 52                 cin >>c[i];  
  53. 53         int count = weight_count();  
  54. 54         cout << count << endl;  
  55. 55 }