贪心例题

1:数列极限

https://ac.nowcoder.com/acm/problem/50166
思路:
考虑3个数a,b,c. a < b < c,有三种取法:
m1 = (ab+1)c = abc + c
m2 = (ac+1)b = abc + b
m3 = (bc+1)a = abc + a
m1 > m2 > m3
可以看出来要最后值最大的话优先取两个小的数,值最小的话优先取两个最大的数。

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#define LL long long
#define inf 0x3f3f3f3f
const int mod = 1e9+7;
using namespace std;

int main()
{
    int n;
    priority_queue<int,vector<int>,less<int> >q1;
    priority_queue<int,vector<int>,greater<int> >q2;
    cin >> n;
    for(int i = 0; i < n; i++){
        int x;
        cin >> x;
        //sl.push_back(x);
        q1.push(x);
        q2.push(x);
    }
    cin >> n;
    int mmin,mmax;
    while(q1.size() != 1){
        int a = q1.top();
        q1.pop();
        int b = q1.top();
        q1.pop();
        q1.push(a*b+1);
    }
    mmax = q1.top();
    while(q2.size() != 1){
        int a = q2.top();
        q2.pop();
        int b = q2.top();
        q2.pop();
        q2.push(a*b+1);
    }
    mmin = q2.top();
    int m = mmin - mmax;
    cout << m;
    return 0;
}

2:均分纸牌

思路:
1:这类问题一般是让所有的数到平均数次数最少。
2:我们要移动的次数最少,那么对于每堆牌,我们考虑最多移动一次,因为移动两次或两次以上是一种浪费。采用“移动一次使得一堆牌数达到平均值”的贪心策略:先把每堆的牌数减去平均数,然后由左而右的顺序移动纸牌。若第i堆纸牌的张数a[i]不为0,则将值移动到下一堆。
3:求出最后的a[i]后,我们可以发现a[i]<0表示需要到右边堆去拿a[i]张牌,那么第i+1堆离平均数为a[i+1] += a[i],a[i]>0那么我们就拿a[i]张牌给第i+1堆,那么第i+1堆离平均数为a[i+1] += a[i]。
https://ac.nowcoder.com/acm/problem/16739

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#define LL long long
#define inf 0x3f3f3f3f
const int mod = 1e9+7;
using namespace std;

int main()
{
    int a[105],n,sum;
    cin >> n;
    sum = 0;
    for(int i = 1; i <= n; i++) cin >> a[i],sum += a[i];
    int ave = sum / n;
    for(int i = 1; i <= n; i++) a[i] -= ave;
    int ans = 0;
    for(int i = 1; i <= n; i++){
        if(a[i] != 0) a[i+1] += a[i],ans++;
//        if(a[i] != 0){
//            //a[i+1] += a[i];
//            if(a[i] < 0) cout << i+1 << "-->" << i << ":" << abs(a[i]) << endl;
//            else cout << i << "-->" << i+1 << ":" << a[i] << endl;
//        } 
    }
    cout << ans;
    return 0;

3:接水问题

思路:从每一组接水的人中选出接水时间最少的那个人,让下一个人接替他的位置接水并加上他的接水时间,这样依次算出每个水龙头的接水总时间,最后选最长节水时间即可。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
using namespace std;

//void print(char a[])
//{
//    printf("%d %c\n",strlen(a),a[2]);
//} 

int main()
{
	int n,m,a[100005],b[105];
	cin >> n >> m;
	int ans = 0,mmax = 0;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 1; i <= n; i++){
		int k = 1;
		for(int j = 1; j <= m; j++){
			 if(b[k] > b[j]){
			 	k = j;
			 }
		}
		b[k] += a[i];
	}
	for(int i = 1; i <= m; i++) {
		mmax = max(mmax,b[i]);
	}
	cout << mmax;
	return 0;
}

4:删数问题

贪心策略:优先从最高位查找,如果从前往后是递增的,则删除递增序列的最后一个,如果递减就删除递减序列的第一个。
一段string的操作代码:
int main()
{
	string s;
	cin >> s;
	s.erase(s.begin()+0);
	s.insert(s.begin()+0,'2');
	cout << s;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
using namespace std;

int main()
{
	string s;
	int m,n;
	while(cin >> s){
		scanf("%d",&m);
		for(int i = 1; i <= m; i++){
			int n = s.length();
			for(int i = 0; i < n; i++){
				if(i == n - 1){
					s.erase(s.begin()+i);
					break;
				}
				if(s[i] > s[i + 1]){
					s.erase(s.begin()+i);
					break;
				}
			}
		} 
		int flag = 0;
		n = s.length();
		for(int i = 0; i < n; i++){
			if(s[i] == '0' && flag == 0) continue;
			else{
				cout << s[i];
				flag = 1;
			}
		}
		if(flag == 0) cout << '0';
		cout << "\n";
	}
    return 0;
}

4:货仓选址

给定数轴上的n个点,在数轴上的所有点中,中位数离所有顶点的距离之和最小。凡是能转化为这个模型的题目都可以用中位数求解。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <string.h>
#include <cmath>
#include <bitset>
#include <set>
#include <map>
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const ll ds = 1e15+7;
const double p = 3.141592653589793238462643383;
using namespace std;

int a[100005];
int main()
{
    int n,x,m,t;
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    sort(a+1,a+n+1);
    int ans = 0;
    int d;
    if(n & 1) d = (a[n/2+1] ) / 2;
    else d = (a[n/2] + a[n/2+1]) / 2;
    for(int i = 1; i <= n; i++){
    	ans += abs(a[i] - d);
	}
	cout << ans;
	return 0;
}


全部评论

相关推荐

字节 飞书绩效团队 (n+2) * 15 + 1k * 12 + 1w
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
10-05 10:13
已编辑
HHHHaos:让这些老登来现在秋招一下,简历都过不去
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务