USACO  Milking Cows

    本题的大概意思是这样的:给你N个喂养奶牛的开始时间和结束时间的时间段。问题是:输出最长的喂养时间段和最长的没有喂养的时间段。(友情提示:这些区间可能会有重复)
    本题最常用的一种算法使用线段树解。不过我没有采用那种做法,本人采用的是用链表合并记录。先把n个区间排序(开始时间相同的按结束时间排序,否则按开始时间排序)。这样做的好处是我们只需要讨论结束时间就可以了。(因为开始时间大小已经确定了)然后经过和并(就是遍历链表,如果可以插入本节点,那么就插入,插入的方法是更新本节点的结束时间,然后再用本节点更新或删除后面的节点。否者,直接把本时间段插入到链表末尾)。具体代码如下:
#include<iostream>
#include<fstream>
#include<algorithm>

using namespace std;

struct milkedtime{
int begin,end;
};

milkedtime ar[5005];

struct savemilkedtime{
int begin,end;
savemilkedtime *next;
};
savemilkedtime *root;
int n,MaxMilking,MaxNoMilking;

int cmp(milkedtime p,milkedtime q){
if(p.begin==q.begin)
return p.end<q.end;
return p.begin<q.begin;
}

void save(int x){
savemilkedtime *h=root;
savemilkedtime *t=new savemilkedtime();
int flag=1;
while(h->next!=NULL){
h=h->next;
if(flag && h->end>=ar[x].begin){//将该时间段更新
h->end=h->end>ar[x].end?h->end:ar[x].end;
flag=0;
}
if(!flag){
while(h->next!=NULL){//更新或删除后面的节点
savemilkedtime *t;
t=h->next;
if(t->begin<=h->end){
h->end=h->end>t->end?h->end:t->end;
h->next=t->next;
delete t;
}
}
break;
}
}
if(flag && h->next==NULL){//没有出现合并的情况
savemilkedtime *t=new savemilkedtime();
t->begin=ar[x].begin;
t->end=ar[x].end;
h->next=t;
t->next=NULL;
return;
}
}

void make(){
int i;
root=new savemilkedtime();
root->next=NULL;
    for(i=0;i<n;i++)
save(i);
}

void output(){//统计
    savemilkedtime *h,*t=root;
MaxMilking=0;MaxNoMilking=0;
while(t->next!=NULL){
t=t->next;
if(MaxMilking<t->end-t->begin)
MaxMilking=t->end-t->begin;
if(t->next!=NULL){
h=t->next;
if(MaxNoMilking<h->begin-t->end)
MaxNoMilking=h->begin-t->end;
}
}
}

int main(){
int i;
ifstream fin("milk2.in");
ofstream fout("milk2.out");
fin>>n;
for(i=0;i<n;i++)
fin>>ar[i].begin>>ar[i].end;
sort(ar,ar+n,cmp);
make();
output();
fout<<MaxMilking<<" "<<MaxNoMilking<<endl;
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值