贪心算法

贪心算法例题及思路

[区间选点] 
Q(1):n个区间,每个区间至少一个点,问最少几个点。
[最大不相交区间数量] 
衍生Q:n个区间,选取最多无交集的区间。
A(1):按照右端点排序,将点选在右端点。

衍生Q例题 
accoders的【一本通提高篇贪心】 活动安排 2032
题意:
求最多无交集区间。
思路:
就是板子 ,按右端点排序,
如果这个区间的左端点大于当前结束时间,就更新结束时间,ans++。 
code:
#include<bits/stdc++.h>
using namespace std;
struct node{
	int s,f;
	bool operator<(const node &W) const{
		return f<W.f;
	}
}a[1001];
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].s>>a[i].f;
	} 
	sort(a+1,a+n+1);
	int sum=0,r=0;
	for(int i=1;i<n;i++){
		if(r<=a[i].s){
			r=a[i].f;
			sum++;
		}
	}
	cout<<sum;
	return 0;
}

Q(1)演变例题:
accoders的【一本通提高篇贪心】 种树2033,一区间内多点
题意 :
每个区间需要至少xi个点有树,区间会重叠。 
思路 :
还是按右端点排序,取右端点,先将此区间内已经种上的树苗减去,然后从右端点向左端点种树苗,如果此位置种过了就向前推一个。 
code:
#include<bits/stdc++.h>
using namespace std;
struct node{
	int l,r,w;
	bool operator<(const node &W) const{
		return r<W.r;
	}
}a[30001]; 
bool vis[30001];
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>a[i].l>>a[i].r>>a[i].w; 
	}
	sort(a+1,a+m+1);
	int ans=0;
	for(int i=1;i<=m;i++){
		int w=a[i].w;
		for(int j=a[i].l;j<=a[i].r;j++){
			if(!w){
				break;
			}
			if(vis[j]){
				w--;
			}
		}
		if(!w){
			continue;
		}
		for(int j=a[i].r;j>=a[i].l;j--){
			if(!w){
				break;
			}
			if(!vis[j]){
				ans++;
				vis[j]=1;
				w--;
			}
		}
	}
	cout<<ans;
	return 0;
}
 
[区间覆盖]
Q(2):给定一个大区间,问多少小区间能覆盖大区间。
A(2):小区间按照左端点排序,选右端点最靠右且左端点不大于大区间左端点的,然后将该小区间的右端点设为大区间左端点,重复上述操作。
Q(2)板子:
accoders的【贪心区间问题】907. 区间覆盖 10110
code: 
#include<bits/stdc++.h>
using namespace std;
struct node{
	int l,r;
	bool operator <(const node &W) const{
		return l<W.l;
	}
}a[100010];
int main(){
	int l,r;
	cin>>l>>r;
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].l>>a[i].r;
	} 
	sort(a+1,a+n+1);
	int i=1,ans=0;
	while(l<r){
		int vis=-1e9,j;
		for(j=i;j<=n;j++){
			if(a[j].l<=l){
				vis=max(vis,a[j].r);
			}else{
				break;
			}
		}
		if(l<r&&a[i].l>l){
			cout<<-1;
			return 0;
		}
		ans++;
		l=vis;
		i=j; 
	}
	cout<<ans;
	return 0;
}
Q(2)例题 
accoders的【一本通提高篇贪心】 喷水装置2034,勾股定理加大区间覆盖
题意:
二维大区间覆盖。 
思路:
通过勾股定理求出区间左端点和右端点,不考虑半径不大于w/2的喷头,然后进行求大区间覆盖。 
code:
#include<bits/stdc++.h>
using namespace std;
struct node{
	double l,r;
	bool operator<(const node &W) const{
		return l<W.l;
	}
}a[15001];
int cnt=0;
int n;
double l,w;
int main(){
	int T;
	cin>>T;
	while(T--){
		cnt=0;
		cin>>n>>l>>w;
		double w2=w/2.0;
		for(int i=1;i<=n;i++){
			double x,y;
			cin>>x>>y;
			if(y<=w/2){
				continue;
			}
			a[++cnt].l=x-sqrt(y*y-w*w/4);
			a[cnt].r=x+sqrt(y*y-w*w/4);
		}
		sort(a+1,a+cnt+1);
		double s=0,e=l;
		int i=1,ans=0,t=0;
		while(s<e){
			double vis=-2e9;
			int j;
			for(j=i;j<=cnt;j++){
				if(a[j].l<=s){
					vis=max(vis,a[j].r);
				}else{
					break;
				}
			}
			if(s<e&&vis<s){
				cout<<-1<<"\n";
				t=1;
				break;
			}
			ans++;
			s=vis;
			i=j;
		}
		if(!t)cout<<ans<<"\n";
	}
	return 0;
}
[区间分组] 
Q(3):n个区间,分成几组,组内无交集,问最少能分成几组。 
A(3):按左端点排序 

Q(3)例题:
accoders【贪心区间问题】906. 区间分组10109
单纯板子
code: 
#include<bits/stdc++.h>
using namespace std;
struct node{
	int l,r;
	bool operator <(const node &W) const{
		return l<W.l;
	}
}a[100010];
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].l>>a[i].r;
	}
	sort(a+1,a+n+1);
	priority_queue<int, vector<int>, greater<int> > q;
	for(int i=1;i<=n;i++){
		if(q.empty()||q.top()>=a[i].l){
			q.push(a[i].r);
		}else{
			q.pop();
			q.push(a[i].r);
		}
	}
	cout<<q.size();
	return 0;
}

贪心其他例题:
1.
accoders的【一本通提高篇贪心】 加工生产调度2035
luogu 的 P1248 加工生产调度

思路:
先求出每一个物品的AB时间最小值,然后排序,
将A机器时间从前向后排入q序列,将B机器时间从后向前排入q序列,
最后模拟求得总时间。 

code(按照洛谷题干写):
 #include<bits/stdc++.h>
using namespace std;
struct node{
	int w,id;
	bool operator<(const node &W) const{
		return w<W.w;
	}
}s[1001];
int a[1001],b[1001],n;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
	}
	for(int i=1;i<=n;i++){
		s[i].w=min(a[i],b[i]);
		s[i].id=i;
	}
	sort(s+1,s+n+1);
	int q[1001]={};
	int l=0,r=n+1;
	for(int i=1;i<=n;i++){
		if(s[i].w==a[s[i].id]){
			q[++l]=s[i].id;
		}else{
			q[--r]=s[i].id;
		}
	}
	int tia=0,tib=0;
	for(int i=1;i<=n;i++){
		tia+=a[q[i]];
		tib=max(tia,tib);
		tib+=b[q[i]];
	}
	cout<<tib<<"\n";
	for(int i=1;i<=n;i++){
		if(q[i]){
			cout<<q[i]<<" ";
		}
	}
	return 0;
}

2.
accoders的【一本通提高篇贪心】 智力大冲浪2036  
luogu的P1230 智力大冲浪 

思路:
将罚金从大到小排序,然后从最后实现时间向前推,若无时间可插则扣罚金。 

code:  
#include<bits/stdc++.h>
using namespace std;
struct node{
	int ti,m;
	bool operator <(const node &W) const{
		return m>W.m;
	}
}a[501];
int vis[501];
int main(){
	int m,n;
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].ti;
	}
	for(int i=1;i<=n;i++){
		cin>>a[i].m;
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		int f=0;
		for(int j=a[i].ti;j>=1;j--){
			if(!vis[j]){
				vis[j]=1;
				f=1;
				break;
			}
		}
		if(!f){
			m-=a[i].m;
		}
	}
	cout<<m;
	return 0;
}

3.
accoders的【一本通提高篇贪心】 钓鱼2041  
luogu的P1717 钓鱼 
思路:
不走回头路,只向前走,然后向大根堆中压入路过池塘的鱼的数量,每次弹出最多的然后减去减少的,
然后重新压入堆 ,重复以上过程求走到每个池塘后的max。 
测后自写代码:www.luogu.com.cn/paste/j83dvxau 
code:
#include<bits/stdc++.h>
using namespace std;
int ff[101],df[101],ti[101];
struct node{
	int id,w;
	bool operator <(const node &W) const{
		return w<W.w;
	}
};
int main(){
	int n,h;
	cin>>n;
	cin>>h;
	h=h*12;
	node t;
	int ans=-1,lt,sum;
	for(int i=1;i<=n;i++){
		cin>>ff[i];
	}
	for(int i=1;i<=n;i++){
		cin>>df[i];
	}
	for(int i=1;i<n;i++){
		cin>>ti[i];
		ti[i]+=ti[i-1];//前缀和 
	}
	for(int i=1;i<=n;i++){
		lt=h-ti[i-1],sum=0;
		if(lt<=0){
			break;
		}
		priority_queue<node> q;
		for(int j=1;j<=i;j++){
			q.push({j,ff[j]});
		}
		for(int j=1;j<=lt;j++){
			t=q.top();
			q.pop();
			if(t.w<0){
				break;
			}
			sum+=t.w;
			q.push({t.id,t.w-df[t.id]});
		}
		ans=max(ans,sum);
	}
	cout<<ans;
	return 0;
}
4.
accoders的【一本通提高篇贪心】 糖果传递
luogu的P2512 [HAOI2008] 糖果传递

code:
#include<bits/stdc++.h>
using namespace std;
int a[1001001];
long long c[1001001],sum;
long long n;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    long long ave=sum/n;
    for(int i=n;i>=1;i--){
        c[i]=c[i+1]+ave-a[i];
    }
    c[1]=0;
    sort(c+1,c+1+n);
    long long ans=0;
    for(int i=1;i<=n;i++){
        ans+=abs(c[i]-c[(n+1)/2]);
    }
    cout<<ans<<"\n";
    return 0;
}
posted @ 2025-01-16 19:04  lbh123  阅读(66)  评论(0)    收藏  举报