BZOJ3419[POI2013]taxis——贪心

题目大意:

一条线段有三个点,0为初始位置,d为出租车总部位置,m为家的位置,人要叫车,有n辆车可以提供,每辆车有一个路程上限,并且都从车站出发,叫的车行驶之后不必须回到车站,问最少叫几辆车。

 

一定能想到的贪心策略是每次选最大的,但现在给这么一组数据:

12 4 5

2 3 4 5 8

发现先选最大的到不了m处了。

因为从出租车站到家只需要一辆车就够了,所以先选出比m-d大的车中路程上限最小的作为从车站到家的车,然后再贪心选最大的。

这里有几个细节要注意:

1、如果贪心选最大的的时候发现能直接到家,那么预留出来的车就没用了,要把答案减1。

2、预留出来的车可以先出车站一段去接人后再开往家。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll m,d;
int n;
ll a[500010];
bool cmp(ll x,ll y)
{
    return x>y;
}
ll mn;
ll now;
ll stop;
int ans;
int flag;
int main()
{
    scanf("%lld%lld%d",&m,&d,&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++)
    {
        if(a[i]>=m-d)
        {
            mn=a[i];
            flag=i;
        }
    }
    stop=d-((mn-(m-d))/2);
    ans++;
    for(int i=1;i<=n;i++)
    {
        if(i==flag)
        {
            continue;
        }
        if(a[i]<stop-now)
        {
            printf("0");
            return 0;
        }
        if(now>=stop)
        {
            break;
        }
        now=a[i]-(d-now)+now;
        ans++;
        if(now>=m)
        {
            ans--;
            break;
        }
    }
    if(now<stop)
    {
        printf("0");
        return 0;
    }
    printf("%d",ans);
}
posted @ 2018-09-20 17:58  The_Virtuoso  阅读(208)  评论(0编辑  收藏  举报