回顾-贪心专题

洛谷1090 合并果子
题意·:把两堆放到一堆花费两堆的和体力,将所有堆最后合成一个堆,求最小体力
分析:贪心寻找最小挪法,每次将最小的两堆合在一起
写法1
这个开始ac的后来看题解不晓得为啥能过,大概是数据太弱,大家直接看2把

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>

using namespace std;

const int N = 1e5+10;
int n,sum=0;
int a[N];

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%d",&a[i]);

    for(int i=0;i<n-1;i++)
    {
        sort(a+i,a+n);//每次找最小两个
        int x=a[i]+a[i+1];
        sum+=x;
        a[i+1]=x;
    }
    printf("%d\n",sum);
    return 0;
}
写法2

使用优先队列,非常简单,但是数据大的话可能过不了
每次取最前面的两个数也就是最小

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<vector>

using namespace std;

int n,sum=0;
priority_queue<int,vector<int>,greater<int> >q;

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        q.push(x);
    }
    for(int i=0;i<n-1;i++)
    {
        int a=q.top();q.pop();
        int b=q.top();q.pop();
        sum+=a+b;
        q.push(a+b);
    }
    printf("%d\n",sum);
    return 0;
}

洛谷 7427 玩游戏

题意:两个人比分为a和b 能不能在n个回合达到这个分数(i回合硬,加i分)
分析:先判断是不是能达到a和b的分数的和 1~n的和 等差数列求和
sum=n(n+1)/2* 若可以得到分数,则贪心求出第一个人赢的回合,从大到小寻找 避免回溯

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

//开 long long

long long a,b;
long long sum=0;

int main()
{
    scanf("%lld%lld",&a,&b);

    long long n=sqrt(2*(a+b));

    if(n*(n+1)!=2*(a+b))printf("No\n");//1~n求和 判断是否存在
    else
    {
        printf("%lld",n);
        for(long long i=n;a;i--)//从大到小寻找 避免回溯
        {
            if(i<=a)
            {
                a-=i;
                printf(" %lld",i);
            }
        }
    }

}

P1684 考验
题意: 每段四行诗的韵脚只可能是“AABB”, “ABAB”, “ABBA” 和“AAAA”中的一种。每句诗句的韵脚都编了号,具有相同编号的句子代表有相同的韵脚。现在,黄药师想删掉一些句子,使得剩下的都是遵循押韵规则的四行诗,而且不允许改变诗句的顺序。找出满足条件最长的诗歌
分析:贪心 观察韵脚 两个A和两个B 则sum++ 当A和B相同 也sum++

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;

const int N = 5100;

int n,sum;
map<int,int>m;

int main()
{
    int s=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        m[x]++;
        if(m[x]==2)s++;
        if(s==2)//各有两个情况 A B
        {
            s=0;
            sum++;
            m.clear();
        }
        if(m[x]==4)//四个一样 A=B
        {
            s=0;
            sum++;
            m.clear();
        }
    }
    printf("%d\n",sum);

    return 0;
}

Acwing 3764. 三元数异或

题意:构造a和b 使得ci=(ai+bi)%3 构造最小max(a,b)
分析:贪心 均衡分配数,当给c一个大的数之后,之后大数都给b,最终达到 max最小,其次就是模拟,从最大位开始遍历构造

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>

using namespace std;

int t,n;
string a,b,c;

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        b=c="";
        scanf("%d",&n);
        cin>>a;
        int flag=0;
        for(int i=0;i<n;i++)
        {
            if(i==0)
            {
                if(a[i]=='0')b+='1',c+='2',flag=1;
                else if(a[i]=='1')b+='2',c+='2';
                else b+='1',c+='1';
                continue;
            }
            
            if(a[i]=='1')
            {
                if(flag)c+='0',b+='1';
                else b+='0',c+='1',flag=1;
            }else if(a[i]=='0')b+='0',c+='0';
            else if(a[i]=='2')
            {
                if(flag)b+='2',c+='0';
                else b+='1',c+='1';
            }
        }
        cout<<b<<endl;
        cout<<c<<endl;
    }
    
    return 0;
}

Acwing 3776. 水果拼盘
题意:有四种水果,数量为a b c d,有两种水果拼盘ad和bcd,价格为e和f,怎么搭配可以得到最大利润

分析:利用贪心的思想,两种拼盘都需要用到d,d是题眼,先不考虑d,按照拼盘的水果最多分为,a和min(b,c) ,然后考虑怎样分配d达到最大利润,分为四种情况

  1. 现有的d大于两种拼盘所需要的d,两种拼盘都可以拼成
  2. 两种拼盘需要的d都大于现有的d,两种拼盘找最大利润
  3. 一个需要大于d,一个需要小于d,比较是 都给第一种 | 给第二种给满,剩下的给第一种,哪种利润更高
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>

using namespace std;

int t;
int a,b,c,d,e,f;

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        int sum=0;
        scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
        int x=a,y=min(b,c);
        
        if(x+y<=d)
            sum=x*e+y*f;
        else if(x>=d&&y>=d)
            sum=max(d*e,f*d);
        else if(x>=d)
            sum=max(d*e,y*f+(d-y)*e);
        else if(y>=d)
            sum=max(d*f,x*e+(d-x)*f);
        else
            sum=max(x*e+f*(d-x),y*f+(d-y)*e);
            
        printf("%d\n",sum);
    }
    
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值