杭电OJ 3190 (贪心)Stall Reservations

Stall Reservations
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 4328 Accepted: 1547 Special Judge

Description

Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will only be milked over some precise time interval A..B (1 <= A <= B <= 1,000,000), which includes both times A and B. Obviously, FJ must create a reservation system to determine which stall each cow can be assigned for her milking time. Of course, no cow will share such a private moment with other cows. 

Help FJ by determining:
  • The minimum number of stalls required in the barn so that each cow can have her private milking period
  • An assignment of cows to these stalls over time
Many answers are correct for each test dataset; a program will grade your answer.

Input

Line 1: A single integer, N 

Lines 2..N+1: Line i+1 describes cow i's milking interval with two space-separated integers.

Output

Line 1: The minimum number of stalls the barn must have. 

Lines 2..N+1: Line i+1 describes the stall to which cow i will be assigned for her milking period.

Sample Input

5
1 10
2 4
3 6
5 8
4 7

Sample Output

4
1
2
3
2
4

Hint

Explanation of the sample: 

Here's a graphical schedule for this output: 

Time     1  2  3  4  5  6  7  8  9 10

Stall 1 c1>>>>>>>>>>>>>>>>>>>>>>>>>>>

Stall 2 .. c2>>>>>> c4>>>>>>>>> .. ..

Stall 3 .. .. c3>>>>>>>>> .. .. .. ..

Stall 4 .. .. .. c5>>>>>>>>> .. .. ..

Other outputs using the same number of stalls are possible.

首先根据hint里边的提示看懂题意:

(当然是我的理解(没有看题干)但是意识相对了)

给你n头牛,给你栅栏,栅栏是一种长方形的东西 ,牛有身长,不能让两只牛重叠身体部分,求问用最少的栅栏来放牛,.第一行输出这个最少栅栏,之后的n行表示按照给出的顺序把牛分配进栅栏,输出栅栏号.

这个题目想了很久,说实话想清楚思路简单,作为新手的我们来说代码经验不足想去实现还是比较困难的一件事.

这里分两块模板进行详解:
1.如何排序.

我们知道,如果我们有一堆牛,我们要把他们放在同一个栅栏里边,如果我们想要最多的牛放在这个栅栏里边,我们要先做到的事情是理清思路,不能一味的放.这里给出实例:

2 4

9 12

3 6

5 8

9 10

11 12

如果是读者你先放进去一头牛你先放哪个? 当然是先放进去 2 4然后用4和 其他的开头比较,这个时候我们发现 5 9 11都比4大,这几头牛都可以放进栅栏里边,这个时候也不要一味的放,先看见顺序靠前的 9 12就放在里边,因为这个时候放进去了 9 12 我们就要拿12和后边的比较,发现这并不是最好的方案,那难道是 9 10? 9 10 还能有个 11 12放进去,但是很可惜,这个方案还是不够好,这个时候我们就要用贪心的思维去想了,到底如何才能得到最好的解呢?

------------------小的数开始,小的数结束。上例中

5 8

9 10

11 12

9 12

这几个牛都能放进去,但是小的数开始,小的数结束的那头牛是 5 8.

所以我们试着放进去 5 8,然后是

9 10

11 12

9 12

我们依旧按照以上的规律来办--------------小的开始,小的结束.9是小的开始,10是相对12的小的结束.

这个时候我们再放进去 9 10

最后我们放进去 11 12

我们发现这样去放的确实得到的最优解.

然后我们就有了排序的观点:

小的开始,小的结束。

这里我们知道结构体排序无法完成两个变量的同时排序。所以我们这里引用一个优先队列.来完成两个变量的最小排序.

代码来源:http://blog.csdn.net/chang_mu/article/details/40982387

struct Node2 {  
    int num, u, v;  
    friend bool operator<(const Node2& a, const Node2& b) {  
        return a.v > b.v;  //小的结束.
    }   
} cow[maxn];  
int ans[maxn];  
  
bool cmp(const Node2& a, const Node2& b) {  
    return a.u < b.u;  //小的开始.
}  
  

然后我们要解决第二个问题:

输出顺序的问题,我们这里输出顺序是按照牛入栅栏的顺序来办的,而并不是按最优解办的,这个时候我们就要有个标记来完成.

标记每个结构体的输入顺序,然后我们还需要一个数组来存输出的答案:

int ans[maxn];  //输出的数组.
        for(i = 0; i < N; ++i) {  
            scanf("%d%d", &u, &v);  
            cow[i].num = i + 1;//用这个来完成标记~  
            cow[i].u = u;  
            cow[i].v = v;  
            ans[i + 1] = 0;  //初始化.
        }  

我们核心思路是要小的开始,小的结束~

我们先按照开始的数从小到大排序:

        sort(cow, cow + N, cmp);  

然后队列里边按照结束的数从小到大排序:

    friend bool operator<(const Node2& a, const Node2& b) 
    {  
        return a.v > b.v;  
    }   

这里排序之后的cow数组保证从小到大的开始.

这里队列保证从小到大的结束.

然后我们要做的事情就是用队头的元素的结束的数和cow数组里边的开始的数进行比较:

        priority_queue<Node2> PQ;  //优先队列的建立方式.
        PQ.push(cow[0]);  //我们首先把第一个cow放进队列。
        ans[cow[0].num] = ++sum;  //sum表示有多少个栅栏。
  
        for(i = 1; i < N; ++i) //每一头牛都要塞进去.
        {
            tmp = PQ.top();  //这里保证队头的结束的数足够小
            if(cow[i].u > tmp.v) //这里保证了当前这头牛的开始的数也足够小.//如果满足了这个条件,就相当于两头牛放在一个栅栏里边了.
            {  
                tmp.v = cow[i].v;  //这个时候我们要pop掉当前队头并且push进去新的结束的数(两头牛在里边,结束的数变大了)
                ans[cow[i].num] = ans[tmp.num];  
                PQ.pop(); PQ.push(tmp);  
            }
             else //否则就要新开一个栅栏.
            {  
                ans[cow[i].num] = ++sum;  
                PQ.push(cow[i]);  
            }  
        }  
  

然后思路理清了这里是AC代码完整的:

#include <stdio.h>  
#include <string.h>  
#include <algorithm>  
#include <queue>  
  
#define maxn 50010  
using namespace std;  
  
struct Node2 {  
    int num, u, v;  
    friend bool operator<(const Node2& a, const Node2& b) 
    {  
        return a.v > b.v;  
    }   
} cow[maxn];  
int ans[maxn];  
  
bool cmp(const Node2& a, const Node2& b) {  
    return a.u < b.u;  
}  
  
int main() {  
    int N, i, j, sum, u, v, flag;  
    Node2 tmp;  
    while(scanf("%d", &N) == 1) {  
        sum = 0;  
        for(i = 0; i < N; ++i) {  
            scanf("%d%d", &u, &v);  
            cow[i].num = i + 1;  
            cow[i].u = u;  
            cow[i].v = v;  
            ans[i + 1] = 0;  
        }  
        sort(cow, cow + N, cmp);  
  
        priority_queue<Node2> PQ;  
        PQ.push(cow[0]);  
        ans[cow[0].num] = ++sum;  
  
        for(i = 1; i < N; ++i) 
        {
            tmp = PQ.top();  
            if(cow[i].u > tmp.v) 
            {  
                tmp.v = cow[i].v;  
                ans[cow[i].num] = ans[tmp.num];  
                PQ.pop(); PQ.push(tmp);  
            }
             else 
            {  
                ans[cow[i].num] = ++sum;  
                PQ.push(cow[i]);  
            }  
        }  
  
        printf("%d\n", sum);  
        for(i = 1; i <= N; ++i)  
            printf("%d\n", ans[i]);  
    }  
    return 0;  
}  































Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值