ZOJ@2874-Paratroopers

ZOJ@2874-Paratroopers

ZOJ@2874
题意:给一个n*m的网格,网格中某些位有敌人,现在可以在网格边上的x轴或者y轴设置炮台,x炮台可以消灭所在列上的所有敌人,y炮台可以消灭所在行上的所有敌人。现在给定修建x炮台,y炮台的费用,问如何设置炮台,使得消灭所有敌人总费用最少(总费用为设置炮台费用之积)。
解法:最大流。首先对炮台费用求对数,使得总费用之积转化为之和。建图:从源点连有向边到x轴,边的容量为在该处设置炮台的费用;y轴上的点连有向边到汇点,边容量为在该点设置炮台的费用;如果网格中点(x,y)处有敌人,则从x处连边到y,边的容量设置为无穷大。

Code
//  2389416      2011-01-19 19:57:39        Accepted      2874      C++      40      352      redsea
#include < cstdio >
#include
< algorithm >
#include
< vector >
#include
< cmath >
using   namespace  std;
#define  MAXN 105 
#define  inf 1000000000.00
double  map[MAXN][MAXN];
double  flow[MAXN][MAXN];
double  max_flow( int  n, double  mat[][MAXN], int  source, int  sink, double  flow[][MAXN]){ 
    
int  pre[MAXN],que[MAXN],p,q,t,i,j;
    
double  d[MAXN];
    
double  tmp;
    
if  (source == sink)  return  inf; 
    
for  (i = 0 ;i < n;i ++
        
for  (j = 0 ;j < n;flow[i][j ++ ] = 0 ); 
    
for  (;;){ 
        
for  (i = 0 ;i < n;pre[i ++ ] = 0 ); 
        pre[t
= source] = source + 1 ,d[t] = inf; 
        
for  (p = q = 0 ;p <= q &&! pre[sink];t = que[p ++ ]) 
               
for  (i = 0 ;i < n;i ++
                
if  ( ! pre[i] && (tmp = mat[t][i] - flow[t][i])) 
                     pre[que[q
++ ] = i] = t + 1 ,d[i] = d[t] < tmp ? d[t]:tmp; 
                
else   if  ( ! pre[i] && (tmp = flow[i][t])) 
                 pre[que[q
++ ] = i] =- t - 1 ,d[i] = d[t] < tmp ? d[t]:tmp; 
        
if  ( ! pre[sink])  break
        
for  (i = sink;i != source;) 
               
if  (pre[i] > 0
                flow[pre[i]
- 1 ][i] += d[sink],i = pre[i] - 1
               
else  
                flow[i][
- pre[i] - 1 ] -= d[sink],i =- pre[i] - 1
    } 
    tmp 
=   0 ;
    
for  (i = 0 ;i < n;tmp += flow[source][i ++ ]); 
    
return  tmp; 
}
int  main()
{
    
int  T, n, m, l, s, t;
    
double  x;
    scanf(
" %d " , & T);
    
while (T -- ){
        scanf(
" %d%d%d " , & m, & n, & l);
        s 
=   0 ;
        t 
=  m + n + 1 ;
        
for ( int  i  =   0 ; i  <  n + m + 2 ; i ++ )
            
for ( int  j  =   0 ; j  <  n + m + 2 ; j ++ )
                map[i][j] 
=   0 ;
        
for ( int  i  =   1 ; i  <=  m; i ++ ){
            scanf(
" %lf " , & x);
            map[s][i] 
=  log10(x);
        }
        
for ( int  i  =  m + 1 ; i  <=  n + m; i ++ ){
            scanf(
" %lf " , & x);
            map[i][t] 
=  log10(x);
        }
        
for ( int  i  =   0 ; i  <  l; i ++ ){
            
int  sx, sy;
            scanf(
" %d%d " , & sx, & sy);
            map[sx][m
+ sy]  =   10 ;
        }
        printf(
" %.4lf\n " , pow( 10.0 , max_flow(n + m + 2 ,map,s,t,flow)));
    }
    
return   0 ;
}



你可能感兴趣的:(ZOJ@2874-Paratroopers)