动态规划——砝码称重

问题描述:

设有1g2g3g5g10g20g的砝码各若干枚(其总重1000g),要求:

输入:

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

输出:

Total=N (N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)

输入样例1  1  0   0   0   0

输出样例Total=3,表示可以称出1g2g3g三种不同的重量

动态规划求解:

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

 

 

 

你可能感兴趣的:(c,ini,iostream)