基础贪心问题

本文介绍了12个编程问题,涉及背包问题、队列操作、线段覆盖、数据结构如小根堆的应用、优化糖果分配等,展示了在IT技术中如何通过算法解决实际问题。
摘要由CSDN通过智能技术生成

1.部分背包问题

在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 110;
double v[N], w[N];
pair<double, int> a[N];
int n, m;

int main(){
	cin>>n>>m;
	double x, y;
	for(int i = 0; i < n; i++){
		cin>>v[i]>>w[i];
		a[i] = {w[i] / v[i], i};
	}
	sort(a, a + n, greater<pair<double, int>>());
	double sum = 0, ans = 0;
	int i = 0;
	while(sum + v[a[i].second] <= m && i < n){
		sum += v[a[i].second];
		ans += w[a[i].second];
		i++;
	}
	if(sum < m && i < n){
		double x = m - sum;
		ans += x * a[i].first;
	}
	printf("%.2lf", ans);
	return 0;
}

2.排队接水

在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
pair<double, int> a[N];
int n; 

int main(){
	cin>>n;
	double x;
	for(int i = 0; i < n; i++){
		cin>>x;
		a[i] = {x, i};
	}
	sort(a, a + n);
	double sum = 0;
	int m = n;
	for(int i = 0; i < n; i++){
		cout<<a[i].second + 1<<" ";
		m--;
		sum += m * a[i].first;
	}
	cout<<endl;
	sum /= n;
	printf("%.2lf", sum);
	return 0;
}

3.线段覆盖

按区间右端点升序排序,如果能接上就接
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
pair<int, int> a[N];
int n; 

bool cmp(const pair<int, int>& p, const pair<int, int>& q){
	return p.second < q.second;
}

int main(){
	cin>>n;
	int x, y;
	for(int i = 0; i < n; i++){
		cin>>x>>y;
		a[i] = {x, y};
	}
	sort(a, a + n, cmp);
	int st, ed = -1e9;
	int cnt = 0;
	for(int i = 0; i < n; i++){
		if(a[i].first >= ed){
			st = a[i].first;
			ed = a[i].second;
			cnt++;
		}
	}
	cout<<cnt;
	return 0;
}

4.合并果子

用小根堆维护最小值,每次取出两个最小值
在这里插入图片描述

#include<iostream>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int>> q;
int n; 

int main(){
	cin>>n;
	int x;
	for(int i = 0; i < n; i++){
		cin>>x;
		q.push(x);
	}
	int sum = 0, a = 0, b = 0;
	while(q.size() > 1){
		a = q.top();
		q.pop();
		b = q.top();
		q.pop();
		sum += a + b;
		q.push(a + b);
	}
	cout<<sum;
	return 0;
}

5.小A的糖果

如果两个相邻的多了,那就先减去第二个,因为第二个还关联第三个
在这里插入图片描述

#include<iostream>
#include<queue>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n, m; 

int main(){
	cin>>n>>m;
	for(int i = 0; i < n; i++){
		cin>>a[i];
	}
	long long sum = 0;
	for(int i = 0; i < n - 1; i++){
		if(a[i] + a[i + 1] > m){
			int x = a[i] + a[i + 1] - m;
			if(a[i + 1] >= x) a[i + 1] -= x;
			else{
				a[i] -= x - a[i + 1];
				a[i + 1] = 0;
			}
			sum += x;
		}
	}
	cout<<sum;
	return 0;
}

6.删数问题

删掉下坡数
在这里插入图片描述

#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n, m; 
string s;

int main(){
	cin>>s;
	cin>>n;
	int len = s.size();
	for(int i = 0; i < len; i++){
		a[i] = s[i] - '0';
	}
	while(n--){
		for(int i = 0; i < len; i++){
			if(a[i] > a[i + 1]){
				for(int j = i; j < len; j++) a[j] = a[j + 1];
				len--;
				break;
			}
		}
	}
	int z = 0, st = 0;
	while(a[z] == 0 && st < len - 1){
		z++, st++;
	}
	for(int i = st; i < len; i++){
		cout<<a[i];
	}
	return 0;
}

7.陶陶摘苹果(升级版)

按花费力气升序排序,先摘花费力气小的
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
pair<int, int> q[N];
int n, m, a, b;

bool cmp(const pair<int, int>& pp, const pair<int, int>& qq){
	if(pp.second != qq.second) return pp.second < qq.second;
	else return pp.first < qq.first; 
}

int main(){
	cin>>n>>m;
	cin>>a>>b;
	int x, y;
	for(int i = 1; i <= n; i++){
		cin>>x>>y;
		q[i] = {x, y};
	}
	sort(q + 1, q + n + 1, cmp);
	int cnt = 0;
	for(int i = 1; i <= n; i++){
		if(m - q[i].second >= 0 && a + b >= q[i].first){
			cnt++;
			m -= q[i].second;
		}
	}
	cout<<cnt;
	return 0;
}

8.铺设道路

大的带着小的填,如果后面一个大于前一个高度,那就多填这个差值,最后加上第一个需要填的高度
在这里插入图片描述

#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n;

int main(){
	cin>>n;
	for(int i = 0; i < n; i++) cin>>a[i];
	int ans = 0; 
	for(int i = 1; i < n; i++){
		if(a[i] > a[i - 1]){
			ans += a[i] - a[i - 1];
		}
	}
	ans += a[0];
	cout<<ans;
	return 0;
}

9.混合牛奶

按照价格升序排序,先买便宜的
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 2e6 + 10;
pair<int, int> q[N];
int n, m;

int main(){
	cin>>n>>m;
	int x, y;
	for(int i = 0; i < m; i++){
		cin>>x>>y;
		q[i] = {x, y};
	}
	//cout<<"-------------------"<<endl;
	sort(q, q + m);
	int ans = 0, sum = 0;
	for(int i = 0; i < m; i++){
		if(sum + q[i].second <= n){
			ans += q[i].first * q[i].second;
			sum += q[i].second;
			//cout<<ans<<endl;
		}else if(sum < n){
			ans += (n - sum) * q[i].first;
			sum = n;
			break;
		}else if(sum >= n){
			break;
		}
		//cout<<q[i].first<<" "<<sum<<endl;
	}
	cout<<ans;
	return 0;
}

10.纪念品分组

让大的和小的组合
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 3e4 + 10;
int a[N];
int n, m;

int main(){
	cin>>m>>n;
	for(int i = 0; i < n; i++) cin>>a[i];
	sort(a, a + n, greater<int>());
	int cnt = 0;
	for(int i = 0, j = n - 1; i <= j; i++){
		if(a[i] + a[j] <= m){
			j--;
		}
		cnt++;
	}
	cout<<cnt;
	return 0;
}

11.跳跳!

高低高低,反复跳
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 3e4 + 10;
long long a[N];
int n, m;

int main(){
	cin>>n;
	for(int i = 0; i < n; i++) cin>>a[i];
	sort(a, a + n, greater<int>());
	long long sum = 0, ed = 0;
	for(int i = 0, j = n - 1; i <= j; i++, j--){
		sum += (a[i] - ed) * (a[i] - ed);
		sum += (a[j] - a[i]) * (a[j] - a[i]);
		ed = a[j]; 
	}
	cout<<sum;
	return 0;
}

12.分组(难)

二分查找当前满足条件的最后一个小组,如果可以进这个小组,那就进去,否则就新建一个小组
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int a[N], q[N], siz[N];
int n, m;

int main(){
	cin>>n;
	for(int i = 0; i < n; i++) cin>>a[i];
	sort(a, a + n);
	q[0] = 1e9;
	int cnt = 0, res = 0;
	for(int i = 0; i < n; i++){
		int l = 0, r = cnt + 1;
		while(l + 1 < r){
			int mid = (l + r) / 2;
			if(a[i] < q[mid]) r = mid;
			else l = mid;
		}
		if(a[i] == q[l]){
			q[l]++, siz[l]++;
		}else{
			q[++cnt] = a[i] + 1, siz[cnt] = 1;
		}
	}
	int ans = 1e9;
	for(int i = 1; i <= cnt; i++){
		ans = min(ans, siz[i]);
	}
	cout<<ans;
	return 0;
}

13.国王游戏(难)

按照左手和右手乘积升序排序,所得的奖赏之和最少
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e3 + 10;
pair<int, int> q[N];
int n, m;

bool cmp(const pair<int, int>& pp, const pair<int, int>& qq){
	if(pp.first * pp.second != qq.first * qq.second) return pp.first * pp.second < qq.first * qq.second;
	else if(pp.first != qq.first) return pp.first < qq.first;
	else return pp.second > qq.second;
}

int main(){
	cin>>n;
	int a, b;
	for(int i = 0; i <= n; i++){
		cin>>a>>b;
		q[i] = {a, b};
	}
	sort(q + 1, q + n + 1, cmp);
	long long ans = 0, sum = 0, res = 1;
	for(int i = 1; i <= n; i++){
		cout<<q[i].first<<" "<<q[i].second<<endl;
		res *= q[i - 1].first;
		sum = res / q[i].second;
		ans = max(ans, sum);
	}
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值