Truck Tour

Problem Statement

Suppose there is a circle. There are  N  petrol pumps on that circle. Petrol pumps are numbered  0  to  (N1)  (both inclusive). You have two pieces of information corresponding to each of the petrol pump: (1) the amount of petrol that particular petrol pump will give, and (2) the distance from that petrol pump to the next petrol pump.

Initially, you have a tank of infinite capacity carrying no petrol. You can start the tour at any of the petrol pumps. Calculate the first point from where the truck will be able to complete the circle. Consider that the truck will stop at each of the petrol pumps. The truck will move one kilometer for each litre of the petrol.

Input Format

The first line will contain the value of  N .
The next  N  lines will contain a pair of integers each, i.e. the amount of petrol that petrol pump will give and the distnace between that petrol pump and the next petrol pump.

Constraints:
1N105
1amount of petrol, distance109

Output Format

An integer which will be the smallest index of the petrol pump from which we can start the tour.

Sample Input

3
1 5
10 3
3 4

Sample Output

1

Explanation

We can start the tour from the second petrol pump.

利用优先队列优化计算dp[i],复杂度O(NlongN)

#include <cmath>
#include <cstdio>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100010;
typedef long long ll;

struct Node {
    ll s;
    int id;
    Node() {}
    Node(ll t_s, int t_id) : s(t_s), id(t_id) {}
    bool operator < (const Node &p) const {
        return s > p.s;
    }
};

priority_queue<Node> pq;

void init() {
    while(!pq.empty()) pq.pop();
}

inline ll max(ll a, ll b) {
    return a > b ? a : b;
}

inline ll min(ll a, ll b) {
    return a < b ? a : b;
}

int arr[maxn];
ll pre[maxn], minv[maxn];
ll dp[maxn];

int main() {

    Node now;
    int ans = -1;
    int n, a, b;
    scanf("%d", &n);
    pre[0] = 0; minv[0] = 0;
    init();
    for(int i = 1; i <= n; ++i) {
        scanf("%d %d", &a, &b);
        arr[i] = a - b;
        pre[i] = pre[i-1] + arr[i];
        pq.push(Node(pre[i], i));
        if(i == 1) {
            minv[i] = pre[i];
        } else {
            minv[i] = min(minv[i-1], pre[i]);
        }
    }
    now = pq.top();
    for(int i = 1; i <= n; ++i) {
        while(now.id < i) {
            pq.pop();
            now = pq.top();
        }
        dp[i] = now.s - pre[i-1];
    }
    for(int i = 1; i <= n; ++i) {
        if(dp[i] >= 0) {
            ll t = pre[n] - pre[i-1];
            if(t + minv[i-1] >= 0) {
                ans = i;
                break;
            }
        }
    }
    printf("%d\n", ans - 1);
    return 0;
}

今天刷UVA恰巧又遇到这道题,这次构思+编码也就几分钟的时间,其实计算一些必要的信息,最后进行O(n)的枚举即可,之前做复杂了,囧~~~~
UVA 11093
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
#include <numeric>
#include <algorithm>
#include <functional>
using namespace std;
const int maxn = 100010;
int a[maxn], b[maxn];
int mld[maxn], mrd[maxn];
int suma[maxn], sumb[maxn];

int main() {

    //freopen("aa.in", "r", stdin);

    int T, n;
    int kcase = 0;
    scanf("%d", &T);
    while(T--) {
        kcase++;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &b[i]);
        }
        mld[1] = a[1];
        suma[1] = a[1];
        sumb[1] = 0;
        for(int i = 2; i <= n; ++i) {
            mld[i] = min(mld[i-1], suma[i-1] - sumb[i-1] - b[i-1]);
            suma[i] = suma[i-1] + a[i];
            sumb[i] = sumb[i-1] + b[i-1];
        }
        mrd[n] = a[n];
        suma[n] = a[n];
        sumb[n] = 0;
        for(int i = n - 1; i >= 1; --i) {
            mrd[i] = min(a[i] - b[i], mrd[i+1] + (a[i] - b[i]));
            suma[i] = suma[i+1] + a[i];
            sumb[i] = sumb[i+1] + b[i];
        }
        int ans = -1;
        for(int i = 1; i <= n; ++i) {
            int lf = mrd[i];
            if(lf < 0) continue;
            lf = suma[i] - sumb[i] - b[n];
            if(lf < 0) continue;
            if(mld[i] + lf >= 0) {
                ans = i;
                break;
            }
        }
        if(ans < 0) {
            printf("Case %d: Not possible\n", kcase);
        } else {
            printf("Case %d: Possible from station %d\n", kcase, ans);
        }
    }
    return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值