100book 0005

100book 0005
差分约束系统
说白了就是求不等式组 若不了解差分约束系统推荐看WC06 冯威论文
对于这个题 设xi为第i时刻实际雇佣人数 numi为上限 si=si-1+xi,s0=0 ri题目中提到 则
numi>=si-si-1>=0
si-si-8>=ri (i>=8)
si+s24-si+16>=ri (i<8)
在第3个不等式中出现了3个未知数 但s24重复出现所以可以枚举s24 还可以二分优化
下面是我的代码
#include < iostream >

using   namespace  std;

int  n,m,dis[ 1000 ],num[ 25 ],r[ 25 ];

struct  
{
    
int  u,v,d;
}e[
1000 ];

inline 
bool  relax( int  u, int  v, int  w)
{
    
if (dis[v] > dis[u] + w)
    {
        dis[v]
= dis[u] + w;
        
return   true ;
    }
    
return   false ;
}

inline 
bool  getdis()
{
    
for ( int  i = 1 ;i <= n;i ++ )  dis[i] = 1 << 30 ;
    dis[
0 ] = 0 ;
    
for ( int  i = 1 ;i <= n;i ++ )
       
for ( int  j = 1 ;j <= m;j ++ )
               relax(e[j].u,e[j].v,e[j].d);
    
for ( int  i = 1 ;i <= m;i ++ )  
       
if (relax(e[i].u,e[i].v,e[i].d))
           
return   false ;
    
return   true ;        
}

inline 
void     adde( int  a, int  b, int  c)
{
    e[
++ m].u = a;
    e[m].v
= b;
    e[m].d
=- c;
}

int  main()
{
    freopen(
" input.in " , " r " ,stdin);
    freopen(
" output.out " , " w " ,stdout);
    n
= 24 ;
    
for ( int  i = 1 ;i <= n; ++ i)
        scanf(
" %d " ,r + i);
    
int  g;
    scanf(
" %d " , & g);
    
for ( int  i = 1 ;i <= g; ++ i)
    {
        
int  p;
        scanf(
" %d " , & p);
        
++ num[p + 1 ];
    }
    
int  s = g,ed =- 1 ;
    
for (;;)
    {
        
if (s == ed + 1 )
        {
            printf(
" %d\n " ,s);
            
return   0 ;
        }
        m
= 0 ;
        
int  t = (s + ed) / 2 ;
        
for ( int  i = 1 ;i <= n; ++ i)
        {
            adde(i,i
- 1 , 0 );
            adde(i
- 1 ,i, - num[i]);
        }
        
for ( int  i = 8 ;i <= n; ++ i)
               adde(i,i
- 8 ,r[i]);
         
for ( int  i = 1 ;i < 8 ; ++ i)
             adde(i,i
+ 16 ,r[i] - t);
           
if (getdis())
               s
= t;
        
else
            ed
= t;
    }
}

你可能感兴趣的:(100book 0005)