zju 1013

题目大意是说有3种武器,每种都有一个重量w,一个尺寸s,一个战斗系数d,另外,如果把数量分别为c1,c2,c3的3种武器合在一起用,就会得到战斗系数为d4的新武器。
现在,有1,2,3...,n量车子来运输武器,每量车子都有最大运输重量和最大运输尺寸,现在用车量来运输武器,要求出能达到的最大战斗系数。

这题很明显是一道动态规划题,初看题意感觉跟背包问题挺象的,不过那只是表面现象而已。
设f[i][n1][n2]表示用前i量车子在运 n1件1武器和n2件2武器的条件下能运的第3种武器的最大数量。
那么f[0][0][0]=0
设函数num(i,j,k)表示第i量车子在运j个1武器和k个2武器后最多再能运k个3武器,则
f[i][n1][n2]=f[i-1][n3][n4]+num(i,n1-n3,n2-n4)
具体参数的取值范围详见程序。
另外可以看到f[i]的值只于f[i-1]有关,那么可以用滚动数组来节省空间。
算出f[n]后,就可以枚举i,j了,看f[n][i][j]的情况,算出此情况下的战斗系数,这样就可以求出最大值了。

code:
#include  < iostream >
#include 
< string >
using   namespace  std;

int  main( ) {
    
const   int  MAXN = 501 ;
    
int  pre[ MAXN ][ MAXN ],now[ MAXN ][ MAXN ];
    
int  w1,s1,d1,w2,s2,d2,w3,s3,d3,c1,c2,c3,d4,n;
    
int  ma,mb;
    
int  cases = 0 ;
    
while (cin >> n) {
    cases
++ ;
    
if ( n == 0  )  break ;
    cin
>> w1 >> s1 >> d1 >> w2 >> s2 >> d2 >> w3 >> s3 >> d3 >> c1 >> c2 >> c3 >> d4;
    memset( pre,
255 , sizeof ( pre ) );
    d4
-= c1 * d1 + c2 * d2 + c3 * d3;
    pre[ 
0  ][  0  ] = 0 ;
    ma
= mb = 0 ;
    
for int  i = 0 ;i < n;i ++  ) {
        memset( now,
255 , sizeof ( now ) );
        
int  cw,cs;
        cin
>> cw >> cs;
        
int  maa = ma,mbb = mb;
        
for int  i1 = 0 ;i1 <= maa;i1 ++  )
        
for int  j1 = 0 ;j1 <= mbb;j1 ++  ) {
            
if ( pre[ i1 ][ j1 ] < 0  )  continue ;
            
for int  i11 = i1,tw1 = 0 ,ts1 = 0 ;tw1 <= cw && ts1 <= cs;i11 ++ ,tw1 += w1,ts1 += s1 )
            
for int  j11 = j1,tw2 = tw1,ts2 = ts1;tw2 <= cw && ts2 <= cs;j11 ++ ,tw2 += w2,ts2 += s2 ){
                
if ( ma < i11 ) ma = i11;
                
if ( mb < j11 ) mb = j11;
                
int  da = ( cw - tw2 ) / w3;
                
int  db = ( cs - ts2 ) / s3;
                
if ( da > db ) da = db;
                
if ( now[ i11 ][ j11 ] < pre[ i1 ][ j1 ] + da )
                now[ i11 ][ j11 ]
= pre[ i1 ][ j1 ] + da;
            }
            
        }
        
for int  i11 = 0 ;i11 <= ma;i11 ++  )
        
for int  j11 = 0 ;j11 <= mb;j11 ++  )
            pre[ i11 ][ j11 ]
= now[ i11 ][ j11 ];   
    }
    
int  max = 0 ;
    
for int  i = 0 ;i <= ma;i ++  )
        
for int  j = 0 ;j <= mb;j ++  ) {
        
if ( now[ i ][ j ] < 0  )  continue ;
        
int  t = i * d1 + j * d2 + now[ i ][ j ] * d3;
        
int  a = i / c1;
        
int  b = j / c2;
        
int  c = now[ i ][ j ] / c3;
        
if ( a > b ) a = b;
        
if ( a > c ) a = c;
        
if ( d4 > 0  ) t += a * d4;
        
if ( t > max ) max = t;
        }
    
if ( cases > 1  ) cout << endl;
    cout
<< " Case  " << cases << " " << max << endl;
    }
    
return   0 ;
}


你可能感兴趣的:(zju 1013)