poj1065

11 篇文章 0 订阅

题目不难,典型的贪心水题。主要是贪心思想。

大致题意为:给定一串木棍的起点和终点,要加工这些木棍。设置初始时加工的木棍需要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;
}
	


 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值