题目不难,典型的贪心水题。主要是贪心思想。
大致题意为:给定一串木棍的起点和终点,要加工这些木棍。设置初始时加工的木棍需要1分钟的等待时间,设初始木棍起点为l,终点为w,其后木棍起点为l',终点为w'。其后若满足条件:l'>=l && w'>=w则加工该木棍不需要等待时间。问加工这些木棍需要的最少等待时间?
题意很明确。贪心策略如下: 将木棍按从起点为第一准则,终点为第二准则从小到大排序。这样以后要想满足l'>=l && w'>=w则必须是排序后后面的木棍。这里针对排序后的木棍。首先检查第一根木棍,标记出后续满足条件l'>=l && w'>=w(记为S)的木棍,然后依次递推,标记第一群木棍。同样的过程标记第二群木棍。这样以后木棍的群数即为需要等待的时间。
下面验证贪心策略的正确性:
1)首先针对一群木棍,由于是排序后的木棍,故要满足条件S,则必须采用上述算法,这样可是第一群木棍的个数最大
2)然后针对后续群木棍,假设由上述算法产生的群木棍状态即为W,其木棍个数为NUM,应该说这是不变化群木棍1情况下的最大个数。若此时在群木棍1中减少一个木棍,将其移到W中,移动后分两种情况:
21)假设群木棍1移动后,本来不再群木棍1中的木棍可以在1中了(即后面的木棍的起点虽然大于前面的木棍,但是终点小于木棍,由于不满足条件S故舍弃了)。
设这些又可以在群木棍1中的木棍编号为B,而移出群木棍1的木棍标号为C,而一定有startC<startB && endC>=endB。若B可以存在中则说明endB>=滚木棍1中C标号前的一个木棍(记作 D),而设置木棍C移到W中了。本身W中是必定存在B的。那么移动后W中必定就失去了B。这样一去一回其实木棍群1和木棍群2中总的木棍数相同,且为相同的木棍。
22)假设群木棍1移动后,没有可以在1中的了。那么即使将木棍移动到W中,最好的情况下也是上述的结论。
这样就可以将所有木棍用最少的群数分配完毕。而群的个数即为最少的等待时间。
下面是代码: 208K+0MS
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#define Max 5010
using namespace std;
int Case,n;
struct Node{
int first;
int next;
}node[Max];
bool flag[Max];
bool cmp(const struct Node p,const struct Node q){ //sort 16MS,qsort 0MS
if(p.first!=q.first)
return p.first<q.first;
else
return p.next<q.next;
}
/*int cmp(const void *p,const void *q){
if( (*(struct Node *)p).first!=(*(struct Node *)q).first )
return (*(struct Node*)p).first-(*(struct Node*)q).first;
else
return (*(struct Node*)p).next-(*(struct Node*)q).next;
}*/
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&node[i].first,&node[i].next);
sort(node+1,node+n+1,cmp); //从小到大排序
//qsort(node+1,n,sizeof(struct Node),cmp);
memset(flag,0,sizeof(flag));
int Sum=0;
int min_greed,index=1;
bool trag;
while(true){ //贪心算法核心
Sum++; //组数即为最少等待时间
trag=true;
min_greed=node[index].next;
flag[index]=true;
for(int i=index+1;i<=n;i++){ //求解每一次的木棍群
if(!flag[i] && node[i].next>=min_greed){
min_greed=node[i].next;
flag[i]=true;
}
else if(!flag[i] && trag && node[i].next<min_greed){
index=i;
trag=false;
}
}
if(trag) //若木棍群都已群完,则结束while
break;
}
printf("%d\n",Sum);
}
return 0;
}