贪心法求解畜栏分配问题

解题思路:

1.按照牛挤奶开始时间进行不递减排序,运用的是折半排序法;

2.从第一头奶牛开始,第一头奶牛肯定放进第一个牛栏里,之后每个奶牛都是与牛栏中开始时间最早的那个相比,如果可以放进去,就放进去啦,如果不能放进去,就重新开一个牛栏。

#include <iostream>
using namespace std;
struct node//存开始时间和结束时间
{
	int no;//初始编号
	int start;
	int end;
	int number=0;//牛栏编号
};
struct niulan//存储每个牛栏的结束时间
{
	int number;//牛栏编号
	int end;
};
void sort(node*  a, int len,char c)//如果c='t'按照结束时间排序,升序,如果c='n',按照初始序号进行排序
{
	int tno, ts, te, tn;
	int low, high, mid;
	if (c == 't')
	{
		for (int i = 1; i < len; i++)
		{
			if (a[i].start < a[i - 1].start)//需要交换
			{
				tno = a[i].no;
				ts = a[i].start;
				te = a[i].end;
				tn = a[i].number;
				low = 0;
				high = i - 1;
				while (low <= high)
				{
					mid = (low + high) / 2;
					if (ts < a[mid].start)//在左边寻找
					{
						high = mid - 1;
					}
					else
						low = mid + 1;
				}
				for (int j = i - 1; j >= low; j--)
				{
					a[j + 1].no = a[j].no;
					a[j + 1].start = a[j].start;
					a[j + 1].end = a[j].end;
					a[j + 1].number = a[j].number;
				}
				a[low].no = tno;
				a[low].start = ts;
				a[low].end = te;
				a[low].number = tn;
			}
		}
	}
	else if (c == 'n')
	{
		for (int i = 1; i < len; i++)
		{
			if (a[i].no < a[i - 1].no)//需要交换
			{
				tno = a[i].no;
				ts = a[i].start;
				te = a[i].end;
				tn = a[i].number;
				low = 0;
				high = i - 1;
				while (low <= high)
				{
					mid = (low + high) / 2;
					if (tno < a[mid].no)//在左边寻找
					{
						high = mid - 1;
					}
					else
						low = mid + 1;
				}
				for (int j = i - 1; j >= low; j--)
				{
					a[j + 1].no = a[j].no;
					a[j + 1].start = a[j].start;
					a[j + 1].end = a[j].end;
					a[j + 1].number = a[j].number;
				}
				a[low].no = tno;
				a[low].start = ts;
				a[low].end = te;
				a[low].number = tn;
			}
		}
	}
}
int min(niulan* a, int len)//找出牛栏中结束时间最早的
{
	int p=0;
	niulan min;
	min.end = a[0].end;
	for (int i = 1; i < len; i++)
	{
		if (min.end > a[i].end)
		{
			min.end = a[i].end;
			p = i;
		}
	}
	return p;
}
int main()
{
	node* a = NULL;
	int N,n;//N是牛的总数,n是需要的牛栏数
	cin >> N;
	a = new node[N];//数组a存储每头牛挤奶的开始时间和结束时间
	for (int i = 0; i < N; i++)
	{
		a[i].no = i;
		cin >> a[i].start;
		cin>> a[i].end;
	}
	sort(a, N,'t');
	a[0].number = 1;
	niulan* head = new niulan[N];
	head[0].number = 1;
	head[0].end = a[0].end;
	int number = 1;
	for (int i = 1; i < N; i++)
	{
		int p = min(head, number);
		if (a[i].start <= head[p].end)//需要重新分配牛栏
		{
			head[number].end = a[i].end;
			head[number].number = number+1;
			number++;
			a[i].number = number;
		}
		else
		{
			head[p].end = a[i].end;
			a[i].number = head[p].number;
		}
	}
	cout << number << endl;
	sort(a, N, 'n');
	for (int i = 0; i < N; i++)
	{
		cout << a[i].number << endl;
	}
    return 0;
}

因为输出的顺序是刚开始输入的顺序,但是在进行排序以后,奶牛的顺序发生了变化,所以要将奶牛写成结构体,存上初始的顺序,还要存上那头牛所在的牛栏编号,当然,考察时间的时候,不能重叠。。。意思就是开始时间为4的不能放进结束时间为4的牛栏里。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值