Peter算法小课堂—贪心算法

A greedy algorithm follows heuristic of making the locally optimal choice at each stage with the intent of finding a global optimum.

思维框架:"每次找最......的物品......"

太戈编程2637题

题目描述:

有n个正整数,现在进行若干次操作:每次删去2个数a和b,然后加入1个数a*b+1。反复操作直到只有一个数,求最小剩下几?

怎样贪心呢?就只有两种可能,①每次挑最小的数合并 ②每次挑最大的数合并。假设有三个数a,b,c,且a<b<c。按①,第一次ab+1和c,第二次(ab+1)*c+1=abc+c+1。按②,第一次bc+1,第二次(bc+1)*a+1=abc+a+1显然小于①,因此采取②方案。即每次挑最大的数合并。注意:数组不能变换长度,得使用multiset(当然,用vector也行)。

代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int n;
int main(){
	cin>>n;
	multiset<int> s;
	multiset<int>::iterator it;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		s.insert(x);
	}
	for(int i=1;i<=n-1;i++){
		it=s.end();
		it--;
		int a=*it;
		s.erase(it);
		it=s.end();
		it--;
		int b=*it;
		s.erase(it);
		s.insert(a*b+1);
	}
	cout<<*s.begin()<<endl;
	return 0;
}

练习1:太戈编程113

太戈编程1744题

题目描述:

n 个人要过河,第i人重w[i]。每艘小船只有2个位置,最大载重为c。求最少要几艘船?

如何贪心呢?答案是"每次挑最轻的人,搭配另1人尽量重,若无人搭配则独自开船"

代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,c,w[100009];
int main(){
	cin>>n>>c;
	for(ll i=1;i<=n;i++) cin>>w[i];
	sort(w+1,w+1+n);
	ll ans=0;
	ll i=1;j=n;
	while(i<j){
		ans++;
		if(w[i]+w[j]<=c) i++,j--;
		else j--;
	}
	if(i==j) ans++;
	cout<<ans<<endl;
	return 0;
}

太戈编程655题

题目描述:

有n辆车大甩卖,第i辆车售价a[i]元。有m个人带着现金来申请购买,第i个到现场的人带的现金为b[i]元,只能买价格不超过其现金额的车子。你是大卖场总经理,希望将车和买家尽量多地进行一对一配对,请问最多卖出多少辆车?

怎样贪心呢?答案是"每次挑最昂贵的车,卖给最富有的人,若卖不出去,则便宜些"。

代码不开放......

太戈编程694题

题目描述:

有 N 堆纸牌,编号分别为 1,2,..., N。每堆上有若干张。可以在任一堆上取若干张纸牌,然后移动。 移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。 现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。输出最少的移动次数,若无解输出-1。

给大家一个概念:集合类问题和序列类问题。集合类问题指不管你怎样调动数据顺序,都不影响结果。序列类问题指不仅要考虑数据的大小,还要考虑数据移动的方向。此题就属于序列类问题。

如何贪心呢?有童鞋会想将纸牌最多的那一堆拆分。比如9 8 17 6,平均数为10,我们就将第三堆分给第一堆1张,给第二堆2张,给第四堆4张,共3次。但考虑一下1 1 17 9 26 6,平均数为10,有两个大于平均数的数,很麻烦。那应该怎样移动呢?

先看1,与平均数差9,从后面往前补9,变成10

再看10和-8,和为2,与2*10差18,从后面往前补18,变成10

再看10和10和-1,何为19,与3*10差11,从后面往前补11,变成10

我们就以这种思路进行下去就是最优解。

代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=109;
int n,ans,s[N],a[N];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
	itn avg=s[n]/n;
	for(int i=1;i<=n-1;i++){
		if(s[i]!=avg*i) ans++;
	}
	cout<<ans<<endl;
	return 0;
}

练习2:太戈编程693题

相关推荐
C++ 老炮儿的技术栈17 分钟前
UDP 与 TCP 的区别是什么?
开发语言·c++·windows·算法·visual studio
殇者知忧20 分钟前
【论文笔记】若干矿井粉尘检测算法概述
深度学习·神经网络·算法·随机森林·机器学习·支持向量机·计算机视觉
mochensage2 小时前
C++信息学竞赛中常用函数的一般用法
java·c++·算法
chengooooooo2 小时前
leetcode Top100 238. 除自身以外数组的乘积|数组系列
算法·leetcode
GUIQU.2 小时前
【每日一题 | 2025年6.2 ~ 6.8】第16届蓝桥杯部分偏简单题
算法·蓝桥杯·每日一题
weixin_527550403 小时前
初级程序员入门指南
javascript·python·算法
嘉陵妹妹5 小时前
深度优先算法学习
学习·算法·深度优先
GalaxyPokemon5 小时前
LeetCode - 53. 最大子数组和
算法·leetcode·职场和发展
hn小菜鸡6 小时前
LeetCode 1356.根据数字二进制下1的数目排序
数据结构·算法·leetcode
zhuiQiuMX6 小时前
分享今天做的力扣SQL题
sql·算法·leetcode