[菜鸟博客]Jack的日常做题记录

贪心算法(外加简单优先队列的使用)

问题链接:poj3190
题目概述:
有 n头牛(1<=n<=50,000)要挤奶。给定每头牛挤奶的时间区
间[A,B] (1<=A<=B<=1,000,000,A,B为整数)。
牛需要呆畜栏里才能挤奶。一个畜栏同一时间只能容纳一头牛。
问至少需要多少个畜栏,才能完成全部挤奶工作,以及每头牛都
放哪个畜栏里(Special judged)
去同一个畜栏的两头牛,它们挤奶时间区间哪怕只在端点重合也是不可以的。
解法思路:
所有奶牛都必须挤奶。到了一个奶牛的挤奶开始时间,就必须为这个奶
牛找畜栏。因此按照奶牛的开始时间逐个处理它们,是必然的。
S(x)表示奶牛x的开始时间。E(x)表示x的结束时间。对E(x), x可以是奶牛,也可以是畜栏。畜栏的结束时间,就是正在其里面挤奶的奶牛的结束时间。同一个畜栏的结束时间是不断在变的。

  1. 把所有奶牛按开始时间从小到大排序。
  2. 为第一头奶牛分配一个畜栏。
  3. 依次处理后面每头奶牛i。处理 i 时,考虑已分配畜栏中,结束时间最
    早的畜栏x。
    若 E(x) < S(i), 则不用分配新畜栏,i可进入x,并修改E(x)为E(i)
    若 E(x) >= S(i),则分配新畜栏y,记 E(y) = E(i)
    直到所有奶牛处理结束
    需要用优先队列存放已经分配的畜栏,并使得结束时间最早的畜栏始终
    位于队列头部。
    证明:
    由于按开始时间的顺序处理奶牛是必然,且按该算法,为奶牛i分配新
    畜栏时,确实是不得不分配的,所以算法正确。
    复杂度: O(nlogn),O(n)用来遍历奶牛,O(logn)用于给奶牛找畜栏,使用优先队列达到这种效率,不然会T…

接下来看代码吧,QAQ。

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<cmath>
#include<vector>
#include<cstring>
#include<queue>
#define N 50001
using namespace std;
struct Cow{
    int a,b;
    int no;
    bool operator<(const Cow &c) const{ return a<c.a;}
}cows[N];
int pos[N],total;
struct Stall{
    int ed;
    int no;
    Stall(int e,int n):ed(e),no(n){}
    bool operator<(const Stall & s) const{
        return ed>s.ed;
    }
};
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&cows[i].a,&cows[i].b);
        cows[i].no=i;
    }
    sort(cows,cows+n);
    priority_queue<Stall> pq;
    for(int i=0;i<n;i++){
        if(pq.empty()){
            total++;
            pq.push(Stall(cows[i].b,total));
            pos[cows[i].no]=total;
        }
        else{
            Stall st=pq.top();
            if(st.ed<cows[i].a){
                pq.pop();
                pq.push(Stall(cows[i].b,st.no));
                pos[cows[i].no]=st.no;
            }
            else{
                total++;
                pq.push(Stall(cows[i].b,total));
                pos[cows[i].no]=total;
            }
        }
    }
    printf("%d\n",total);
    for(int i=0;i<n;i++) printf("%d\n",pos[i]);
    return 0;
}

两个小于号重载,一个用于sort,一个用于建立优先队列。

上一篇:2020一些重要的事


下一篇:JAVA代理