2021-07-18学习记录 poj3190 畜栏分配(贪心算法)

学习记录 poj3190 畜栏分配(贪心算法)

题目描述

vjudge链接
大意:已知有 N ( 1 ≤ N ≤ 50 , 000 ) N (1\le N\le 50,000) N(1N50,000)头奶牛需要在畜栏中挤奶,现给出奶牛总数 N N N及每头奶牛占用畜栏的开始时间 A A A、结束时间 B ( 1 ≤ A ≤ B ≤ 1 , 000 , 000 ) B(1\le A\le B\le 1,000,000) B(1AB1,000,000), 且每个畜栏只能同时供一头奶牛使用,同一个畜栏的使用结束时间和下一次开始使用的时间不重合。求至少建立多少个畜栏才能满足需要,及每头奶牛使用的畜栏编号。

样例输入

第一行输入奶牛的数目$N$,其后每行给出各头奶牛挤奶的开始时间$A$、结束时间$B$,二者用空格隔开。
5
1 10
2 4
3 6
5 8
4 7

输出
第一行输出最少需要的畜栏数目,其后各行输出各头奶牛使用的畜栏编号。
例:第2行输出1表明第一头奶牛 ( A 1 = 1 , B 1 = 10 ) (A_1 = 1, B_1 = 10) (A1=1,B1=10)使用1号(第1个建立的)畜栏。

4
1
2
3
2
4

解题思路

贪心算法
每次开始挤奶只考虑当前情况下的最优解。
对每头奶牛按开始挤奶的时间升序排列(先开始挤奶的排在前面),每个畜栏按结束时用的时间生升序排列(先使用完的排在前面),每次一头奶牛开始挤奶,检验当前最早结束使用的畜栏是否空闲,尽可能充分利用已有畜栏达到最少建立畜栏的目的。

代码

#include <iostream>
#include <algorithm>	//调用sort函数
#include <queue>		//调用优先队列
#include <cstring>		//调用memset()给数组置0

using namespace std;

struct Cow
{
	int b, e;		//开始时间b,结束时间e
	int No;			//奶牛编号
	Cow(): b(1),e(1) { }
	void Set(int bi, int en, int no)
	{
		b = bi;
		e = en;
		No = no;
	}
	//重载 ‘<’ 用于sort函数排序
	bool operator<(const Cow & c) const
	{
		return b < c.b;
	}
	~Cow() { }
};

struct Stall
{
	int end;	//该畜栏使用结束时间
	int No;		//该畜栏编号
	Stall(int e, int n): end(e), No(n) { }
	//重载 ‘<’ 用于优先队列排序
	bool operator < (const Stall & s) const
	{
		return end > s.end;
	}
	~Stall() { }
};

const int MAXN = 50050;
int pos[MAXN];
Cow cows[MAXN];

int main()
{
	int n;
	cin >> n;
//	数组在main函数中用变量n申请时vjudge编译不通过
//	int pos[n];
//	memset(pos, 0, sizeof(pos));
//	Cow cows[n];
	int bi, en;
	for (int i = 0; i < n; i++)
	{
		cin >> bi >> en;
		cows[i].Set(bi, en, i);
	}
	
	sort(cows, cows+n);
//	//排序检验 
//	for (int i = 0; i < n; i++)
//	{
//		cout << cows[i].b << " ";
//	}
//	cout << endl;
	
	int total = 0;		//当前已修建畜栏总数
	priority_queue<Stall, vector<Stall> > pq;
	for (int i = 0; i < n; i++)
	{
		//第一头奶牛开始记奶时新建畜栏
		if (total == 0)
		{
			total++;
			Stall ss(cows[i].e, total);
			pq.push(ss);
			pos[cows[i].No] = total;
		}
		else
		{
			Stall st = pq.top();	//当前最早结束使用的畜栏
			//注意'<',两头奶牛使用同一个畜栏时端点不能重合
			if (st.end < cows[i].b )//有空闲畜栏可用
			{
				pq.pop();
				pos[cows[i].No] = st.No;	//编号为cows[i].No的奶牛使用编号st.No的畜栏
				Stall ss(cows[i].e, st.No);
				pq.push(ss);
			}
			else	//无空闲畜栏可用,新建畜栏
			{
				total++;
				Stall(cows[i].e, total);
				pq.push(ss);
				pos[cows[i].No] = total;
			}
		}
//		//分配检验 
//		for(int j = 0; j < n; j++)
//		{
//			cout << pos[j] << " ";
//		}
//		cout << total << endl;
	}
	
	cout << total << endl; 
	for (int i = 0; i < n; i++)
	{
		cout << pos[i] << endl;
	}
	
	return 0;
}

关于sort排序函数和优先队列

sort(pfirst, pend, cmp);
//pfirst 	指向排序数组的首地址
//pend		指向排序区间末尾的后一位
//cmp		比较函数
priority_queue<int, vector<int>, less<int> > q;

关于其中比较函数的个人看法:
cmp也可以看作“优先级”比较函数,不写比较函数时,sort默认从小到大排列,实际上cmp函数返回true时优先级高,故排在前面。相对的,优先队列中默认从大到小排列,比较函数返回true优先级低,排在后面。
详见大佬的帖子
优先队列
版权声明:本文为CSDN博主「C20182030Epic」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/c20182030/article/details/70757660

sort函数
版权声明:本文为CSDN博主「EvanOne(文一)」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41139830/article/details/80624216

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值