畜栏保留问题(贪心)

畜栏保留问题

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.

做的使用超时,暂时直到使用优先队列保证结束时间的有序,可以节省时间

上代码

#include <bits/stdc++.h>

using namespace std;

struct node{
    int no;
    int b;
    int e;
    int a;
    bool operator < (const node &aa)const
    {
        return e>aa.e;
    }
}cattle[50010];
int a[50010];
priority_queue<node> q;

int cmp(node a,node b)
{
    if(a.b==b.b)
        return a.e < b.e;
    return a.b < b.b;
}
int main()
{
    int n,num;
    scanf("%d",&n);
    num = n;
    for(int i = 0;i < n;i++)
    {
        scanf("%d%d",&cattle[i].b,&cattle[i].e);
        cattle[i].no = i;
    }
    sort(cattle,cattle+n,cmp);
    int ans = 0;
    for(int i = 0;i < n;i++)
    {
        if(!q.empty()&&q.top().e < cattle[i].b)
        {
            a[cattle[i].no] = a[q.top().no];
            q.pop();
            q.push(cattle[i]);
        }
        else
        {
            ans++;
            a[cattle[i].no] = ans;
            q.push(cattle[i]);
        }
    }
    printf("%d\n",ans);
    for(int i = 0;i < n;i++)
    {
        printf("%d\n",a[i]);
    }
    return 0;
}
### Java 实现贪心算法解决奶牛问题 为了满足题目要求,可以采用贪心策略来分配畜栏。具体来说: - 将所有奶牛按其开始时间从小到大排序[^1]。 - 使用优先队列维护当前可用的畜栏结束时间。 - 遍历每一头奶牛时,如果最早结束使用的畜栏能够容纳这头新来的奶牛,则更新该畜栏的新结束时间为当前奶牛的结束时间;否则新开辟一个畜栏。 下面是具体的Java代码实现: ```java import java.util.*; class Cow { int start; int end; public Cow(int s, int e) { this.start = s; this.end = e; } } public class BarnAllocation { public static List<Integer> allocateBarns(List<Cow> cows) { Collections.sort(cows, (a, b) -> Integer.compare(a.start, b.start)); PriorityQueue<Integer> ends = new PriorityQueue<>(); Map<Integer, Integer> cowToBarnMap = new HashMap<>(); // 记录每头牛对应的畜栏编号 for (int i = 0; i < cows.size(); ++i) { Cow currentCow = cows.get(i); if (!ends.isEmpty() && ends.peek() < currentCow.start) { // 当前最早的结束时间小于等于要加入的cow的起始时间,说明这个barn是可以复用的 int earliestEnd = ends.poll(); // 更新此barn新的end time为currentCow的endTime ends.offer(currentCow.end); // 找到earliestEnd所在的barn并将其映射至currentCow for(Map.Entry<Integer, Integer> entry : cowToBarnMap.entrySet()){ if(entry.getKey().equals(earliestEnd)){ cowToBarnMap.put(currentCow.end, entry.getValue()); break; } } } else { // 否则开辟一个新的barn,并记录下它的end time以及对应关系 ends.offer(currentCow.end); cowToBarnMap.put(currentCow.end, ends.size()); } } // 构建返回的结果列表 List<Integer> result = new ArrayList<>(cows.size()); for(Cow c : cows){ result.add(cowToBarnMap.get(c.end)-1); // barn index starts from 0 } return result; } public static void main(String[] args) { List<Cow> cows = Arrays.asList( new Cow(1, 5), new Cow(2, 8), new Cow(7, 9) ); System.out.println("Cows allocated to barns: " + allocateBarns(cows)); } } ``` 这段程序实现了基于贪心算法的解决方案,通过合理利用现有资源(即尽可能重复使用已经存在的畜栏),从而最小化所需总数量。此外,在实际应用中可以根据实际情况调整比较方式或数据结构以优化性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值