HDU 1350 Taxi Cab Scheme

题意:给出了N趟要去载人的时刻表,有时间,初始地址(a,b),目标地址(c,d),载人花费的时间为|a-c|+|b-d|。如果一辆出租车载完当前的一趟,如果他可以从当前位置赶到某趟的其实位置,并在出发时间前1分钟,那么这辆车就可以载他。问出租车公司至少要派出多少辆车才能完成这个任务。

解:由于时间是不能有交的。一辆车按照一个最优的策略,载完这趟就去下趟,才能使得派出的车辆最少。这就和最小路径覆盖模型类似了。

再回顾下最小路径覆盖:有向无环图中,从一些顶点出发,一个人可以按照给定的有向图往前走(别人走了的顶点,不能走),问要遍历完这个图上所有的顶点,最少需要多少人。

  问题就转化为在有向无环图中找出最少的不相交的路径,这些路径覆盖图中所有的顶点。

看图:

可以在①点放一个人,他可以遍历①②③点,在⑧点放一个人,他可以遍历⑧④⑤⑦,最后再再⑥这里放一个人。

所以答案是三。

我们把有向无环图转化为二分图,拆出N个点。最小路径覆盖数=N-最大匹配。


回过头来看这道题,是不是很类似,要选取最少的路径覆盖所有顶点(把每趟载人看成一个点)。

#include<iostream>
#include<string>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<math.h>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define MAXN 505*2
#define LL long long
#define INF 0x3f7f7f7f
vector<int>g[MAXN];
int vis[MAXN],r[MAXN];
int gettime(int h,int m)
{
    return h*60+m;
}
int ABS(int x)
{
    if(x<0)x=-x;
    return x;
}
struct node
{
    int id,cur,need,x1,x2,y1,y2;
}p[MAXN];
bool cmp(node x,node y)
{
    return x.cur<y.cur;
}
bool match(int id)
{
    int sz,j;
    sz=g[id].size();
    for(j=0;j<sz;j++)
    {
        if(!vis[g[id][j]])
        {
            vis[g[id][j]]=1;
            if(r[g[id][j]]==-1||match(r[g[id][j]]))
            {
                r[g[id][j]]=id;
                return true;
            }
        }
    }
    return false;
}
int hungary(int n)
{
    int re=0;
    memset(r,-1,sizeof(r));
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof(vis));
        if(match(i))re++;
    }
    return re;
}
int main()
{
    int t,i,n,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            int h,m;
            scanf("%d:%d%d%d%d%d",&h,&m,&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2);
            p[i].id=i;
            p[i].cur=gettime(h,m);//转化为分钟
            p[i].need=ABS(p[i].x1-p[i].x2)+ABS(p[i].y1-p[i].y2);//跑完这趟需要的时间
            g[i].clear();
        }
        sort(p+1,p+1+n,cmp);//对时刻排序
        for(i=1;i<=n;i++)
        {
            for(j=1+i;j<=n;j++)
            {
                if(p[i].cur+p[i].need+ABS(p[i].x2-p[j].x1)+ABS(p[i].y2-p[j].y1)<p[j].cur)
               //i趟时刻+需要时间+从i趟终点跑到j趟起点时间 < j趟的出发时间  
<span style="white-space:pre">		</span>g[i].push_back(j);
            }
        }
        printf("%d\n",n-hungary(n));
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值