POj-2431 Expedition-优先队列

版权声明:欢迎转载 https://blog.csdn.net/suntengnb/article/details/80027634

问题描述:
A group of cows grabbed a truck and ventured on an expedition deep into the jungle. Being rather poor drivers, the cows unfortunately managed to run over a rock and puncture the truck’s fuel tank. The truck now leaks one unit of fuel every unit of distance it travels.
To repair the truck, the cows need to drive to the nearest town (no more than 1,000,000 units distant) down a long, winding road. On this road, between the town and the current location of the truck, there are N (1 <= N <= 10,000) fuel stops where the cows can stop to acquire additional fuel (1..100 units at each stop).
The jungle is a dangerous place for humans and is especially dangerous for cows. Therefore, the cows want to make the minimum possible number of stops for fuel on the way to the town. Fortunately, the capacity of the fuel tank on their truck is so large that there is effectively no limit to the amount of fuel it can hold. The truck is currently L units away from the town and has P units of fuel (1 <= P <= 1,000,000).
Determine the minimum number of stops needed to reach the town, or if the cows cannot reach the town at all.
AC代码:

priority_queue<int> pq;
struct S//加油站
{
    int d;//距离
    int f;//油量
};
S s[10010];
int n,l,p;
int my_pos = 0,my_fuel = 0;
bool cmp(const S &a,const S &b)
{
    return a.d < b.d;
}
//需要行驶的路程为L,则起点坐标为0,终点坐标为L
int main()
{
    cin >> n;
    for(int i = 1; i <= n; ++i)//输入加油站
        cin >> s[i].d >> s[i].f;
    cin >> l >> p;
    for(int i = 1; i <= n; ++i)//将距终点的距离改为距起点的距离
        s[i].d = l - s[i].d;
    sort(s + 1,s + n + 1,cmp);//按距起点的距离由小到大排序
    my_pos = 0;
    my_fuel = p;
    int id = 1;//从第id个加油站开始考虑
    int cnt = 0;//加油的次数
    while(true)
    {
        my_pos += my_fuel;//行驶油量个距离
        if(my_pos >= l)//如果到达终点
        {
            cout << cnt << endl;
            break;
        }
        my_fuel = 0;//没油了
        for(int i = id; i <= n; ++i)//将已经路过的加油站入队
        {
            if(s[i].d <= my_pos)
                pq.push(s[i].f);
            else
            {
                id = i;
                break;
            }
        }
        if(my_pos < l && pq.empty() == true)//如果还没到终点且队列为空
        {
            cout << -1 << endl;//则无法到达
            break;
        }
        my_fuel += pq.top();//在油最多的那个加油站加油
        cnt++;
        pq.pop();//出队
    }
    return 0;
}

解决方法:
如果按照模拟的思路去考虑,繁杂的判断条件让人很头疼,而且时间复杂度很高。
当路过一个加油站时,是否应该加油是很难确定的,我们在人生中也是这样,总会遇到许多难以抉择的选择,过了许久后,才对选择有了清晰的认识。
既然当前选择难以确定,就放到以后去做。可以这样考虑,在路过加油站i后,我们就获得了穿越回去加油的权力,如果之后需要加油,则时光倒流回到那个加油站加油。
这种等价的考虑会大大简化我们的解题
还要注意段与点的处理,这个画图便知

猜你喜欢

转载自blog.csdn.net/suntengnb/article/details/80027634
今日推荐