POJ 2376 Cleaning Shift

POJ 2376题目大意如下:

有N头牛要在指定的T时间以内工作,但是每头牛的工作时间区间给定了,同时在1~T这T个小时里面,每个小时都至少得有一头牛在工作,如果这种情况不恒成立,那么输出“-1”说明没有解决方案,否则,给出最佳解决方案:使用最少牛的头数

观察到问题的规模并不大,所以可以用暴力搜索来做,但是要注意的一点是:在对这N头牛按照它们的工作时段来排序之后(我的排序是按照先排下限,在下限相等时候再排上限)。所以我开始给出这么一个短路判定:

if (cow[0].left != 1 || cow[N - 1].right < T) printf("-1\n");

然而就是这么一句话,弄得自己提交了不下十次,才发现问题所在:既然排序是在如上所说的情况之下,所以“ cow[N - 1].right < T ”这句话是错误的,因为最后一个时间段的上限不大于等于T,不说明之前的时间段上限不能达到这个值。

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;
const int max2 = 25000;

struct Section{ int left, right; };
Section cow[max2 + 1];

int N, T;

bool comp(const Section& lhs, const Section& rhs) {
    return lhs.left < rhs.left || (lhs.left == rhs.left && lhs.right < rhs.right);
}

void solve() {
    //如果不是从1开始
    if (cow[0].left != 1) printf("-1\n");
    else {
        int i = 0, sum = 1;
        Section flag = cow[0];  //用来作为断定不同牛的一个时间短标准
        while (i < N) {
            int j = i + 1, temp = 0;
            //找到工作时间段最大的那头牛,前提是它的开始时间在上一头牛的时间段以内,而它的结束时间大于上一头牛的结束时间
            while (j < N) {
                if (cow[j].left > flag.right + 1) break;
                else if (cow[j].right > flag.right) {
                    if (cow[temp].right < cow[j].right) temp = j;
                }
                j++;
            }
            if (temp != 0) {
                flag = cow[temp];
                sum++;
                i = temp;
            }
            else i++;
        }
        if (flag.right >= T) printf("%d\n", sum);
        else printf("-1\n");
    }
}

int main(int argc, const char * argv[]) {
    // insert code here...
    scanf("%d %d", &N, &T);
    for (int i = 0; i < N; i++) scanf("%d %d", &cow[i].left, &cow[i].right);
    sort(cow, cow + N, comp);
    solve();
    return 0;
}

Accept 880K / 63MS


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值