HBU算法设计与分析 贪心算法

1.最优会场调度

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef pair<int,int> PII;
PII p[N];
priority_queue<int,vector<int>,greater<int>> q;  //最小堆 存储最早结束的会场的结束时间 
int n;
//其实这个题可以理解为同一个会场在同一个时间内只能进行一个活动 
//现在问所有活动都要正常进行 最少需要几个会场 
int main(){
	cin>>n;
	for(int i=0;i<n;i++) cin>>p[i].first>>p[i].second;
	sort(p,p+n);//默认按照所有活动的开始时间排序 
	q.push(p[0].second); //第一个活动一定不用开新会场 
    //贪心思想:每次直接与最早结束的会场的结束时间相比 只要能用 就用该会场 不能用就代表其他的也会场肯定不能用 直接开一个新会场
	for(int i=1;i<n;i++){
		if(!q.empty()&&p[i].first>=q.top()) q.pop();  
		// 如果最早结束的会场可以容纳当前活动,则复用该会场
		q.push(p[i].second);
	}
	cout<<q.size()<<endl;
	return 0;
} 

2.最优合并

cpp 复制代码
#include <bits/stdc++.h>
using namespace std; 
priority_queue<int> pmax; //大根堆
priority_queue<int,vector<int>,greater<int> > pmin; //小根堆
int n,x;

int getmin(){
	int sum=0;
	while(pmin.size()>1){
		int a=pmin.top();pmin.pop(); 
		int b=pmin.top();pmin.pop();
        //贪心思想:每次取出堆中的两个值 根据堆的性质 取出的值必定为最小的两个值
		sum+=a+b;
		pmin.push(a+b); //计算结果再加入堆中
	}
	return sum;
}
int getmax(){
	int sum=0; //与小根堆计算思想相同
	while(pmax.size()>1){
		int a=pmax.top();pmax.pop();
		int b=pmax.top();pmax.pop();
		sum+=a+b;
		pmax.push(a+b);
	}
	return sum;
}

int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>x;
		pmin.push(x); //将每个值都在两个堆中各入堆一次
		pmax.push(x);
	}
	cout<<getmax()<<" "<<getmin()<<endl;
	return 0;
}

3.程序存储问题

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,sum,cnt,a[100005];
int main() {
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>a[i];
    sort(a,a+n);
    //贪心思想:只要还没达到临界值 就一直加 达到就直接break掉 程序结束
    for(int i=0;i<n;i++){
    	sum+=a[i];
    	if(sum<=m) cnt++; 
    	else break;
	}
	cout<<cnt<<endl;
    return 0;
}

4.最优服务次序问题

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e5+5;
typedef long long LL;
int n,a[N];
int main(){
	cin>>n;
	for(int i=0;i<n;i++) cin>>a[i];
	sort(a,a+n);
    //贪心思想:后面的每一个人都要把他排在他前面的所有时间各等一遍 所以前面的人越短越好 所以直接让每个位置都取 能取到的最短 即直接升序排序
	LL time=0;
	for(int i=0;i<n;i++) time+=(n-i)*(LL)a[i]; //每一个时间被等待了n-i次
	double res=time/(double)n;
	printf("%.2lf",res);
	return 0;
}

5.汽车加油问题

cpp 复制代码
#include <iostream>
using namespace std;
const int N=1e5+5;
int n,k,sum,cnt,a[N];
int main(){
	cin>>n>>k;
	for(int i=0;i<=k;i++) {
		cin>>a[i];
		if(a[i]>=n){
			cout<<"No Solution";
			return 0;
		}
	}
	for(int i=0;i<=k;i++){
		if(sum+a[i]>n){ //贪心思想:尽可能多走 直到无法走 就选择加油
			cnt++;
			sum=0;
	    }
		sum+=a[i];
	}
	cout<<cnt;
	return 0;
}

6.最优分解问题

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n,index,a[100001];
//解题关键点为要是自然数乘积最大 应使其2 3 5 7 小数尽可能多
//eg 5=2+3 但x*5一定小于x*2*3   即若a+b=定值,a-b的绝对值越小,ab值越大 
//所以只需要尽可能找能除尽的小数即可 

vector<int> res={1}; //高精度模板 
vector<int> mul(vector<int> A,int b){
	vector<int> C;
	int t=0;
	for(int i=0;i<A.size()||t;i++){
		if(i<A.size()) t+=A[i]*b;
		C.push_back(t%10);
		t/=10;
	}
	while(C.size()>1&&C.back()==0) C.pop_back();
	return C;
}

int main(){
	cin>>n;

	//初始化第一次分解 
	 //只要n>3 结果中就一定会有2 
	a[index++]=2;
	n-=2; 
	//利用循环分解掉n
	int i=3;
	while(n>a[index-1]){
		a[index]=i++;
		n-=a[index];
		index++;
	} 
	//贪心思想:尽量取小值 在不重复的情况下 尽量把多出来的值 分配给尽可能多的数
	//将剩下的部分x 分为x个一(因为平均分配给每一个比直接分配个某个数+x 要大 上面已证明过) 
	//从大的数开始加 因为从小数开始会重复 
	for (int i=index-1;n>0;i--) {
        a[i]++;
        if(i==0) i=index; // 循环分配
        n--;
    }
	//后几组测试数据位数过大 所以使用高精度转换
	for(int i=0;i<index;i++)  res=mul(res,a[i]); 
	for(int i=res.size()-1;i>=0;i--) cout<<res[i];
	return 0;
} 
相关推荐
EndingCoder5 分钟前
图算法在前端的复杂交互
前端·算法·图算法
kanhaoning24 分钟前
将重排序大模型Qwen3-Reranker-8B的知识蒸馏到小模型BGE-reranker-v2-m3上
算法
Thymme26 分钟前
C++获取时间和格式化时间
c++
CoovallyAIHub28 分钟前
2025年小目标检测分享:从无人机视角到微观缺陷的创新模型
深度学习·算法·计算机视觉
用户403159863966332 分钟前
表达式并发计算
java·算法
前端拿破轮43 分钟前
不是吧不是吧,2025年了还有人不会括号匹配?
算法·leetcode·面试
CoovallyAIHub1 小时前
无人机图像中的小目标检测新利器:深入解析 LAM-YOLO 模型
深度学习·算法·计算机视觉
真的想上岸啊1 小时前
学习C++、QT---25(QT中实现QCombobox库的介绍和用QCombobox设置编码和使用编码的讲解)
c++·qt·学习
刃神太酷啦1 小时前
C++ 多态详解:从概念到实现原理----《Hello C++ Wrold!》(14)--(C/C++)
java·c语言·c++·qt·算法·leetcode·面试
山河木马1 小时前
前端学C++可太简单了:引用
前端·javascript·c++