反悔贪心笔记

反悔贪心笔记

什么是反悔贪心?

贪心理论上是没有反悔一说的,贪心求的就是当前的最优解。但是当前的最优解不一定是全局最优解,所以要进行反悔操作
简单来说,就是当我们贪心时发现某一步不是最优解,我们就退后一步,换一个贪心策略
鉴于此,我们有两个反悔策略:

  • 反悔堆:通过堆来维护当前贪心策略的最优解,若发现最优解不对,就退回上一步,更新最优解。
  • 反悔自动机:作者还在学习中

例题详解

用时一定模型

USACO09OPEN 工作调度Work Scheduling


题意:

NN个工作,每一项工作都有一个截至时间DiD_i,完成工作可得到PiP_i收益,在同一时间我们只能去做一个工作,问最大可以得到多少收益

思路:

先按截止时间排序,然后再遍历,若没有冲突直接做,有冲突用小根堆反悔即可(因为小根堆存储的必定是最小值 )

code:
//Misty_Post coded at 24/1/25 
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n; 
struct nood{
	ll dt;//截止时间
	ll v;//价值 
	bool operator<(const nood &vv)const{//重载运算符 (小根堆需要)
        if (v > vv.v) return 1;
        return 0;
    }
}es[1000000];
priority_queue<nood> q;//小根堆	
bool cmp(nood x,nood y){
	return x.dt<y.dt;
} 
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>es[i].dt>>es[i].v;
	}
	sort(es+1,es+1+n,cmp);
	ll ans=0;
	for(int i=1;i<=n;i++){
		if(es[i].dt>q.size()){//有时间做这个任务 
			ans+=es[i].v;
			q.push(es[i]);
		}
		else{//反悔 
			if(es[i].v>q.top().v){
				ans-=q.top().v;
				q.pop();
				q.push(es[i]);
				ans+=es[i].v;
			}
		}
	}
	cout<<ans;
}

价值一定模型

例题:[JSOI2007]建筑抢修


题意:

我们再来考虑这样一个问题,我们有 n 个任务,每个任务有截止日期和完成耗时。在同一时间我们只能去做一个任务。所有任务的价值都是一样的,问最多能完成多少个任务。

思路:

我们可以用大根堆维护截止日期,若可以安排任务直接安排,不能的话从大根堆中把耗时最长的任务丢掉,正确性显然

code
//Misty_Post coded at 24/1/25  
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n; 
struct nood{
        ll dt;//截止时间
        ll v;//持续时间 
        bool operator<(const nood &vv)const{//重载运算符 (小根堆需要)
        if (v < vv.v) return 1;//更改这里可以变成大根堆 
        return 0;
    }
}es[1000000];
priority_queue<nood> q;//大根堆   
bool cmp(nood x,nood y){
        return x.dt<y.dt;
} 
int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
                cin>>es[i].v>>es[i].dt;
        }
        sort(es+1,es+1+n,cmp);
        ll ans=0;
        for(int i=1;i<=n;i++){
                if(es[i].dt>=ans+es[i].v){//有时间做这个任务 
                        ans+=es[i].v;
                        q.push(es[i]);
                }
                else{
                        //cout<<"**";
                        if(es[i].v<q.top().v){
                                ans-=q.top().v;
                                q.pop();
                                q.push(es[i]);
                                ans+=es[i].v;
                        }
                }
        }
        cout<<q.size();
}
posted @   MistyPost  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示