POJ 1328 3190 贪心 优先队列

来源:互联网 发布:淘宝盗版商品是啥意思 编辑:程序博客网 时间:2024/05/29 04:51

微软题目没思路。。。。再推推吧。。。

POJ 1328

二维的区间覆盖,雷达固定在x轴上,问最少雷达数观测到所有小岛

最开始想着直接按照x轴或者y轴排序贪心,但是发现并不能,很容易就能找到反例,单单按照一个轴的方向排序并不能满足最优性。

考虑把一个点转化为一个区间,这个区间代表需要覆盖到这个点雷达可放置区间

其实和2376差不多,类似这种某个东西覆盖一些点的题目都是把数据转化为轴上可行的区间再操作。

转化为区间之后,将区间按l第一关键字从小到大,r第二关键字从大到小排序,每次判断当前区间和前一个区间是否有重叠。如果有重叠,就把当前区间更新为重叠部分。如果当前区间和前一个区间没有重叠,ans+1。

#include <cstdio>#include <cstdlib>#include <iostream>#include <cmath>#include <algorithm>#define Maxn 1000using namespace std;struct Interval {    double x, y;}inter[Maxn + 10];int n, d, ans, tot, cnt;bool cmp(Interval, Interval);int main() {    //freopen("input.txt", "r", stdin);    //freopen("output.txt", "w", stdout);    while (scanf("%d%d", &n, &d), !(n == 0 && d == 0)) {        cnt = 0;        ans = 0;        for (int i = 1;i <= n;++ i) {            int tempx, tempy;            scanf("%d%d", &tempx, &tempy);            if (tempy > d)                ans = -1;            if (tempy >= 0) {                double temp = sqrt(d * d * 1.0 - tempy * tempy * 1.0);                inter[++ cnt].x = tempx - temp;                inter[cnt].y = tempx + temp;            }        }        if (ans == -1) {            printf("Case %d: %d\n", ++ tot, ans);            continue;        }        double nowx, nowy;        sort(inter + 1, inter + 1 + cnt, cmp);        for (int i = 1;i <= cnt;++ i) {            if (ans == 0 || inter[i].x > inter[i - 1].y)                ++ ans;            else {                inter[i].x = max(inter[i].x, inter[i - 1].x);                inter[i].y = min(inter[i].y, inter[i - 1].y);            }        }        /*for (int i = 1;i <= cnt;++ i)            printf ("\n%.4lf %.4lf", inter[i].x, inter[i].y);*/        printf("Case %d: %d\n", ++ tot, ans);    }    //fclose(stdin);    //fclose(stdout);    return 0;}bool cmp(Interval a, Interval b) {    if (a.x != b.x)        return a.x < b.x;    return a.y > b.y;}

POJ 3190

一如既往的cow风

n个牛要在一个位置上独自榨奶时间L到R,问至少需要多少榨奶位以及每个牛在哪个榨奶位。

先按照起始时间从小到大排序。再维护一个小根堆(或者说优先队列)保存当前建立的榨奶位,该榨奶位当前已被占用到lasttime作为关键字。每次对于当前牛,如果优先队列中top元素的lasttime小于当前牛的起始时间,那么当前牛可以直接被分配到这个榨奶位,再把lastime更新为当前牛的结束时间;如果top元素的lastime都大于当前牛的起始时间,那么需要新建一个榨奶位。每次维护优先队列的同时记录当前牛被分配到的榨奶位序号。

#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>#include <cstring>#include <vector>#include <functional>#include <queue>#define Maxn 50000using namespace std;2zswstruct Interval {    int l, r, num;}inter[Maxn + 10];struct Stall {    friend bool operator < (Stall x, Stall y) {        return x.last > y.last;    }    int num, last;};int n, ans;int stall[Maxn + 10];bool cmp(Interval, Interval);int main() {    scanf("%d", &n);    for (int i = 1;i <= n;++ i) {        scanf("%d%d", &inter[i].l, &inter[i].r);        inter[i].num = i;    }    sort(inter + 1, inter + 1 + n, cmp);    /*for (int i = 1;i <= n;++ i)        printf("%d %d\n", inter[i].l, inter[i].r);*/    priority_queue<Stall> que;    for (int i = 1;i <= n;++ i) {        if (ans == 0) {            stall[inter[i].num] = ++ ans;            Stall temp = {ans, inter[i].r};            que.push(temp);            //printf("Inter %d go to new stall %d\n", inter[i].num, ans);            //printf("top stall last:%d\n", que.top().last);            continue;        }        Stall temp = que.top();        if (temp.last < inter[i].l) {            que.pop();            temp.last = inter[i].r;            stall[inter[i].num] = temp.num;            que.push(temp);            //printf("Inter %d go to existed stall %d\n", inter[i].num, temp.num);        }        else {            Stall tt = {++ ans, inter[i].r};            stall[inter[i].num] = ans;            que.push(tt);            //printf("Inter %d go to new stall %d\n", inter[i].num, ans);        }        //printf("top stall last:%d\n", que.top().last);    }    printf("%d\n", ans);    for(int i = 1;i <= n;++ i)        printf("%d\n", stall[i]);    return 0;}bool cmp(Interval a, Interval b) {    return a.l < b.l;}
0 0
原创粉丝点击