[模拟] UVa11093 Just Finish it up 环形跑道 (模拟之剪枝)

题目

环形跑道给定n个加油站(n<=100000),编号从1到n,输入Pi表示第i个加油站可以加油Pi加仑,Qi表示第i到第i + 1个加油站消耗油量。初始油箱为空,求选择一个起点,使得可以走完一圈回到起点。如果无解输出Not possible,否则输出可以选择的最小起点。

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#define ll long long

const int maxn = 100000 + 1000;
int gas[maxn], dis[maxn], n;
// dis[i]表示 i 与 (i+1)%n 的距离

int solve() {
    int start = 0, s = 0; ll g = 0;
    while (start < n) {
        //printf("start: %d  s: %d\n", start, s);
        g += gas[s];
        if ((s + 1) % n == start) {
            if (g >= dis[s])
                return start;
            else
                return -1;
        }
        if (g < dis[s]) {
            if (s < start) return -1;  // 1,2,...,start-1都非解,而此时s<start,证明s遍历回来了,即start,start+1,...,n-1都不是解。直接驳回。
            start = s + 1;
            g = 0;
            s = start;
        }
        else {
            g -= dis[s];
            s = (s + 1) % n;
        }
    }
    return -1;
}

int main() {
    int T, kase = 0;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        for (int i = 0; i < n; i++) scanf("%d", &gas[i]);
        for (int i = 0; i < n; i++) scanf("%d", &dis[i]);
        int ans = solve();
        if (ans == -1) printf("Case %d: Not possible\n", ++kase);
        else printf("Case %d: Possible from station %d\n", ++kase, ans+1);
    }

    return 0;
}

思路

1.暴力:枚举每个点(O(n)),并判断(O(n))。 复杂度: O(n2) O ( n 2 )
2.暴力+剪枝:枚举每个点,并判断。若从点i出发,在点j到点j+1的路上没油的,那么i,i+1,…,j-1,j都绝对不是解,直接排除。 复杂度: O(n) O ( n )

  • 原因:对于点i到点j后,j点油量p1;点i+1到点j后,j点油量p2。则必有p1>=p2。p1尚且不能从j走到j+1,p2更不可能了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值