您的位置:首页 > 其它

USACO  Milking Cows

2012-11-07 13:05 176 查看
 
 本题的大概意思是这样的:给你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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: