【贪心算法专题】(c++)

分糖果

http://oj.haizeix.com/problem/750 ​ 现在有 n 个正整数,将他们连成一排,组成一个最大的整数。
在这里插入图片描述

v1

一个较为复杂的思路:理解题目,可以发现从左往右分糖果,如果下一个孩子评分更高,则该孩子的糖果数就+1。
比如序列1 2 3 我们分配的糖果也是1 2 3
循环中遇到的另一种情况就是下一个孩子评分更低的情况,这时候可以认为他该分的糖果数为1。
此时需要反过来考虑当前这个孩子是否为1,此时需要从右往左开始考虑,反过来把之前的数字加1。

#include<iostream>
using namespace std;
int main(){
	int n;
	cin>>n;
	int *a = new int[n];
	int *b = new int[n];
	for(int i=0;i<n;i++)
		cin>>a[i];
	b[0] = 1;
	for(int i=1;i<n;i++){
		if(a[i]>a[i-1]){
			b[i]=b[i-1]+1;
		}
		if(a[i]==a[i-1]){
			b[i] = b[i-1];
		}
		if(a[i]<a[i-1]){
			b[i] = 1;
			if(b[i-1]<=1){
				//cout<<"!!!";
				int j=i-1;
				b[j]++;
				while((j-1)>=0 && b[j-1]-b[j]==0){
					j--;
					b[j]++;
				}
			}
		}
	}
	
	int num=0;
	for(int i=0;i<n;i++)
		num+=b[i];
	cout<< num;
		//cout<<b[i]<<" ";
	delete a;
	return 0;
}

v2

简单点的思路是为了保证评分高的孩子获得比评分低的多,这里注意的点是相邻的,因此只用管相邻的就好了。从左到右遍历一次,遇到更大的就加一,否则就置为1。然后从右到左也来一次,方式和第一次相同。此时和,对于每一个小孩来说,需要的糖果数就是这两次遍历中的最大值。这是由于此时该最大值必然会同时满足以上这两种情况。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
	int n;
	cin>>n;
	vector<int> rating(n);
	vector<int> num(n);
	for(int i=0; i<n; i++){
		int data;
		cin >> data;
		rating[i] = data;
	}
	num[0] = 1;
	for(int i=1;i<n;i++){
		if(rating[i]>rating[i-1])
			num[i]=num[i-1]+1;
		else
			num[i] = 1;
		//cout<<"!!"<<num[i]<<" ";
	}	
	int right=0;
	for(int i=n-1;i>=0;i--){
		if(i < n-1 && rating[i]>rating[i+1])
			right++;
		else
			right=1;
		
		//printf("! %d %d",i,right);
		num[i] = max(num[i],right);
	}	
	int ans=0;
	for(int i=0;i<n;i++){
		ans += num[i];
		//cout<<" "<<num[i];
	}
		
	printf("%d",ans);
	return 0;
	
}

分饼干

http://oj.haizeix.com/problem/749 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
在这里插入图片描述
为了尽可能满足最多数量的孩子,从贪心的角度考虑,应该按照孩子的胃口从小到大的顺序依次满足每个孩子,且对于每个孩子,应该选择可以满足这个孩子的胃口且尺寸最小的饼干。(下面的代码实现使用的是从大到小排序,道理相同~)

#include<iostream>
#include<stdlib.h>
using namespace std;

int compare(const void *a, const void *b)
{
    unsigned int *pa = (unsigned int*)a;
    unsigned int *pb = (unsigned int*)b;
    return (*pb) - (*pa );  
}
int main(){
	unsigned int na,nb;
	cin>>na;
	int *a = new int[na];
	for(int i=0;i<na;i++)
		cin>>a[i];
	cin>>nb;
	int *b = new int[nb];
	for(int i=0;i<nb;i++)
		cin>>b[i];
	//cout<<"!~!";
	qsort(a,na,sizeof(unsigned int),compare);
	qsort(b,nb,sizeof(unsigned int),compare);
	//cout<<"!~!";
	int j=0,i=0,num=0;
	for(;i<na && j<nb;i++){
		//cout<<b[j]<<" "<<a[i]<<endl;
		if(b[j]>=a[i]){
			j++;
			num++;
		}
	}
	cout<<num;
	return 0;
}

最大整数

http://oj.haizeix.com/problem/505 ​ 现在有 n 个正整数,将他们连成一排,组成一个最大的整数。
在这里插入图片描述
这个问题的主要思路也是贪心。每一次我都把尽可能”大“的最大数排在前面,这样连接起来的数肯定是最大的。
”大“的判断比较特殊,需要是让两两组合后,能够使得组合后数字较大的数。

  • 这道题的解题思路和对于vector, sort的使用可以好好学习一下。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool cmp(const string &a, const string &b){
	return a+b > b+a;  //这种比较就是会使得最前面的数组合任意数都可以达到最大。
}
int main(){
	int n;
	cin >> n;
	vector <string> nums(n);
	for(int i; i<n; i++)
		cin>>nums[i];
	sort(nums.begin(), nums.end(), cmp);
	string ans;
	for(int i = 0; i < nums.size(); i++){
		ans += nums[i];	
	}
	cout << ans << endl;
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值