砝码称重--多重背包

                                                                                                  砝码称重

Description

设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000)。

Input

输入方式:a1 a2 a3 a4 a5 a6 (表示1g砝码有a1个,2g砝码有a2个,…,20g砝码有a6个)

Output

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

Sample Input

1 1 0 0 0 0   (注:下划线表示空格)

Sample Output

TOTAL=3  表示可以称出1g,2g,3g三种不同的重量

枚举算法:

代码
   
     
#include < stdio.h >
#include
< stdlib.h >
int a1,a2,a3,a5,a10,a20;
int s[ 41001 ] = { 0 };
int sum = 0 ;
int main(){
int i1,i2,i3,i4,i5,i6;
FILE
* in , * out ;
in = fopen( " input10.txt " , " r " );
out = fopen( " output.txt " , " w " );
fscanf(
in , " %d%d%d%d%d%d " , & a1, & a2, & a3, & a5, & a10, & a20);

for (i1 = 0 ;i1 <= a1;i1 ++ )
for (i2 = 0 ;i2 <= a2;i2 ++ )
for (i3 = 0 ;i3 <= a3;i3 ++ )
for (i4 = 0 ;i4 <= a5;i4 ++ )
for (i5 = 0 ;i5 <= a10;i5 ++ )
for (i6 = 0 ;i6 <= a20;i6 ++ )

if ((i1 + i2 + i3 + i4 + i5 + i6) != 0 && s[i1 + i2 * 2 + i3 * 3 + i4 * 5 + i5 * 10 + i6 * 20 ] == 0 )
{
sum
++ ;
s[i1
+ i2 * 2 + i3 * 3 + i4 * 5 + i5 * 10 + i6 * 20 ] = 1 ;
}

printf(
" TOTAL=%d\n " ,sum);
fprintf(
out , " TOTAL=%d\n " ,sum);
system(
" pause " );
fclose(
in );
fclose(
out );
return 0 ;
}



 

动态规划算法:

 

代码
   
     
1 #include < stdio.h >
2 #include < stdlib.h >
3 #include < string .h >
4
5   int a[ 7 ],b[ 7 ],f[ 7 ][ 1001 ],sum = 0 ;
6
7   int main(){
8
9 memset(f, 0 , sizeof (f));
10 FILE * in , * out ;
11 b[ 1 ] = 1 ;b[ 2 ] = 2 ;b[ 3 ] = 3 ;
12 b[ 4 ] = 5 ;b[ 5 ] = 10 ;b[ 6 ] = 20 ;
13 int i,j,i1;
14 in = fopen( " input8.txt " , " r " );
15 out = fopen( " output.txt " , " w " );
16
17 for (i = 1 ;i <= 6 ;i ++ )
18 fscanf( in , " %d " , & a[i]);
19
20 for (j = 1 ;j <= a[ 1 ];j ++ )
21 f[ 1 ][j * b[ 1 ]] = 1 ;
22
23 for (i = 2 ;i <= 6 ;i ++ )
24 for (j = 1 ;j <= 1000 ;j ++ )
25 for (i1 = 0 ;i1 <= a[i];i1 ++ ) // 多重背包比0-1背包多的循环:对砝码个数的控制
26   if (j - i1 * b[i] > 0 )
27 {
28 if (f[i - 1 ][j - i1 * b[i]])
29 f[i][j] = 1 ;
30 }
31 else
32 if (j - i1 * b[i] == 0 )f[i][j] = 1 ;
33
34 for (i = 1 ;i <= 1000 ;i ++ )
35 if (f[ 6 ][i] == 1 )sum ++ ;
36
37 fprintf( out , " TOTAL=%d\n " ,sum);
38 printf( " TOTAL=%d\n " ,sum);
39 system( " pause " );
40 fclose( in );
41 fclose( out );
42 return 0 ;
43 }

       状态转移方程 :if(f[i-1][j-i1*b[i]])  f[i][j]=1;   (0<=i1<=a[i],j-i1*b[i]>0)
                            if(j-i1*b[i]]==0)          f[i][j]=1;  
       该题用动态规划解决的是统计问题f[i][j]的值有两种,1和0,1代表用前i个砝码可以表示j这个重量,
       状态转移思想:看前i-1个砝码是否可以 表示j这个重量,或者是否可以表示j-i1*b[i]这个重量 。i1代表砝码i的
       个数,b[i]代表i的重量。如果j-i1*b[i]==0,说明只用i砝码就可以称出j的重量,也将f[i][j]变为1.     

 

 

你可能感兴趣的:(背包)