白书贪心3题,poj2376\1328\3190

本文分享了三道算法题的解题思路及代码实现,包括任务分配、雷达控制和摊位预定问题。通过实际案例讲解如何高效解决区间覆盖等经典问题,并探讨了不同排序策略对算法性能的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

好几天才做了这三个题。

2376审题错误,fj右1-t个活,根据奶牛的工作时间,找出尽可能少的牛来干。做题的时候将点覆盖考虑乘线段覆盖,纠结了很长时间,hjc提醒我才理解了题意。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<stdio.h>
using namespace std;
const int maxn=25009;
struct node{
	int l,r;
};
int cmp(node a,node b){
	if(a.l!=a.r)return a.l<b.l;
	return a.r<b.r;	
}
int ans=1,n,t,minl=1e7,maxr=0;
node a[maxn];
int main(){
	scanf("%d%d",&n,&t);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a[i].l,&a[i].r);
		minl=min(minl,a[i].l);
		maxr=max(maxr,a[i].r);
	}
	if(minl>1||maxr<t){printf("-1\n");return 0;}			
	sort(a+1,a+1+n,cmp);
	a[n+1].l=t+1,a[n+1].r=t+1;
	int tmpl=1,tmpr=0,f=0,i=2;
	while (i<=n){
		if(a[i].r<=a[tmpl].r){i++;continue;}//被包含的区间,不管
		f=0;
		while(a[i].l<=a[tmpl].r+1){	//找出下一个尽可能靠后的区间,		
			if(a[i].r>tmpr){tmpr=a[i].r;f=i;}
			i++;
		}
		if(f)ans++,tmpl=f,tmpr=0;//选择这个找出的区间
		else {ans=-1;break;}	
	}
	cout<<ans<<endl;
	
}


1328,雷达控制。,将岛屿的位置根据半径映射到直线上,装换为点覆盖直线问题。惯性思维,遇到区间习惯性左端点排序,而本题只需从一个方向考虑,比如从左到右,那么只需要右端点排序。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int n,d;
double x,y;
struct node {
	double l,r;
} a[10009];
bool cmp(node a,node b) {
	//if(a.l!=b.l)return a.l<b.l;
	return a.r<b.r;
}
node dis(double x,double y) {
	node a;
	a.l=x-sqrt(d*d-y*y);
	a.r=x+sqrt(d*d-y*y);
	return a;
}

int main() {
	int T=0;
	while(true) {

		cin>>n>>d;
		if(n==0)break;
		int ans=0;
		for(int i=1; i<=n; i++) {
			scanf("%lf%lf",&x,&y);
			if(y>d)ans=-1;
			a[i]=dis(x,y);
		}
		if(ans==-1){
			cout<<"Case "<<++T<<": "<<ans<<endl;
			continue;
		}
		sort(a+1,a+1+n,cmp);
		double minr;
		for(int i=1; i<=n;) {
			minr=1e9;		
			while(i<=n&&a[i].r<minr)minr=a[i].r,i++;//找出最小右短点,		
			ans++;//标记为导弹的左边缘 ,确定圆心位置minr		
			while(i<=n&&a[i].l<=minr) 
				i++; //向右找导弹能控制的点,
		}
		cout<<"Case "<<++T<<": "<<ans<<endl;
	}
}


3190预定摊位。这个题目本来可以1a,结果看了数据范围不大,用了cin,结果华丽的tml了,改成scanf才170ms,可怜的cin啊,你就这么慢吗?

先左端点排序,然后用优先队列找出最早结束的那个摊位,放上能放的牛

#include<iostream>
#include<queue>
#include<algorithm> 
#include<stdio.h>
using namespace std;
struct node{
	int l,r,id;	
	bool operator < (const node &a) const { //最小值优先,优先队列用 
		return r>a.r ;
    }
}a[50009];
int res[50009]; 
int cmp(node a,node b){//左端点排序用
	return a.l<b.l ;
}
priority_queue<node>q;
int n,ans=1,mans=1;
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		scanf("%d%d",&a[i].l,&a[i].r);
		a[i].id=i;
	}
	sort(a,a+n,cmp);
	for(int i=0;i<n;i++){
	
		if(q.empty()){res[a[i].id]=1;ans=1;}
		else{
			node t=q.top();
			if(a[i].l>t.r){
				q.pop();
				res[a[i].id]=res[t.id];
			}
			else {
				res[a[i].id]=++ans;				
				if(mans<ans)mans=ans;
			}
		} 
		q.push(a[i]);
	}
	cout<<mans<<endl;
	for(int i=0;i<n;i++)cout<<res[i]<<endl ;
	
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值