poj 2060 Taxi Cab Scheme

本文讨论了出租车公司如何高效调度车辆以满足多个预约需求的问题,通过最小路径覆盖算法,实现最少车辆数目的最优调度。算法考虑了预约的时间、地点及行驶时间,运用曼哈顿距离计算两点间行驶时间,并在建图过程中处理了未预约地点的特殊调度需求。

题意:出租车公司有n个预约, 每个预约有时间和地点, 地点分布在二维整数坐标系上, 地点之间的行驶时间为两点间的曼哈顿距离(|x1 - x2| + |y1 - y2|)。一辆车可以在运完一个乘客后运另一个乘客, 条件是此车要在预约开始前一分钟之前到达出发地, 问最少需要几辆车搞定所有预约。

这里用到的知识是  最小路径覆盖 = 总节点数 – 最大独立集数(最大匹配数);

这里建图要注意的是如果这个地方没预约,我们可以从这个地方开到有预约的地方去;所以这个地方要发费时间;

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<vector>
using namespace std;
class Node
{
public:
      int start,end;
      int a,b,c,d;
};
bool G[524][524],visit[524];
int match[524];
bool cmp( Node a , Node b )
{
     return a.start < b.start;    
}
bool path( int num , int N )
{
     for( int i = 1 ; i <= N ; i ++ )
     {
         if( !visit[i] && G[num][i] )
         {
              visit[i] = true;
              if( !match[i] || path( match[i], N ) )
              {
                   match[i] = num;
                   return true;        
              }         
         }        
     }    
     return false;
}
int main(  )
{
    int hour,minute,a,b,c,d,N,n;
    Node node[524];
    while( scanf( "%d",&N )==1 )
    {
       while( N-- )
       {
           scanf( "%d",&n );
           memset( G, 0 , sizeof( G ) );
           memset( match , 0 , sizeof( match ) );
           for( int i = 1; i <= n ; i++ )
           {
               scanf( "%d:%d %d %d %d %d",&hour,&minute,&node[i].a,&node[i].b,&node[i].c,&node[i].d );
               int t = hour * 60 + minute ;
               int tt = abs( node[i].a - node[i].c ) + abs( node[i].b -node[i].d );
               node[i].start = t ; node[i].end = node[i].start  + tt;        
           } 
           sort( node + 1 , node + n + 1 , cmp  );
           for( int i = 1 ; i <= n ; i ++ )
           {    
                for( int j = i+1 ; j <= n ; j ++ )
                {
                    int t = abs(node[i].c-node[j].a) + abs(node[i].d - node[j].b) ;
                    if( node[i].end + t  < node[j].start ) 
                        G[i][j] = true;    
                }        
           }
           int ans = 0 ;
           for( int i = 1 ; i <= n ; i ++ )
           {
                memset( visit , 0 , sizeof( visit ) );
                if( path( i , n ) )
                    ans ++;    
           }
           printf( "%d\n", n - ans );
       }    
    }
    //system( "pause" );
    return 0;
}

 

 

 

转载于:https://www.cnblogs.com/bo-tao/archive/2012/07/05/2577180.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值