贪心算法

本文介绍了贪心算法的基本思想,并通过四个典型题目详细阐述了贪心算法的解题策略,包括购买商品、看电视节目、配置药水浓度和修理墙壁问题。每个问题都提供了解题思路和代码实现,展示如何在不同场景下利用贪心算法求解最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目一:(典型题目)

购买商品
有m元钱,n种物品;每种物品有j磅,总价值f元。(可以使用0.3f购买0.3j物品)
输入:M,N 以及N 种物品的重量和总价格
输出:最多能买到多少磅物品
思路:每次购买剩余物品中性价比最高的物品
代码:

#define _CRT_SECURE_NO_DEPRECATE
/*
贪心算法:购买最多的商品
*/
#include<stdio.h>
#include<algorithm>
using namespace std;
struct goods {
    double j;//物品总重
    double f;//物品总价值
    double s;//单价
    bool operator < (const goods &A) const
    {
        return s < A.s; //升序排列
    }
}buf[1000];
int main()
{
    int m, n;
    while (scanf("%d%d", &m, &n) != EOF)
    {
        if (m == -1 && n == -1)
            break;
        for (int i = 0; i < n; i++)
        {
            scanf("%lf%lf", &buf[i].j, &buf[i].f);
            buf[i].s = buf[i].f / buf[i].j;
        }
        sort(buf, buf + n);
        //有钱并且物品还有
        int index = 0;
        double res = 0;
        while (index < n && m>0)
        {
            if (buf[index].f <= m)
            {
                res += buf[index].j;
                m -= buf[index].f;
            }
            else
            {
                res += buf[index].j*m / buf[index].f;
                m = 0;
            }
            index++;
        }
        printf("%.3lf\n", res);
    }
    return 0;
}

题目二(典型)

看电视节目
输入:N(节目总数),N行节目的开始时间和结束时间
输出:能完整看到的节目个数
解题思路:
优先选择结束时间最早的节目:原因如果最优解的第一个节目不是结束最早的节目,那么我们可以使用一个结束早的来替换,替换后的解是一样的
在选择第x个节目的时候,我们选择在x-1个节目结束的时候,其他所有可以收看的节目结束时间最早的节目
代码:

#define _CRT_SECURE_NO_DEPRECATE
/*
贪心算法:可以看到电视节目总数
*/
#include<stdio.h>
#include<algorithm>
using namespace std;
struct program {
    int startTime;
    int endTime;
    bool operator < (const program &A) const {
        return endTime < A.endTime;
    }
}buf[100];
int main()
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        if (n == 0) break;
        for (int i = 0; i < n; i++)
        {
            scanf("%d%d", &buf[i].startTime, &buf[i].endTime);
        }
        sort(buf, buf + n);
        //对排序后的节目进行遍历
        int currentTime = 0;
        int res = 0;
        for (int i = 0; i < n; i++)
        {
            if (currentTime <= buf[i].startTime)
            {
                currentTime = buf[i].endTime;
                res += 1;
            }
        }
        printf("%d\n", res);
    }
    return 0;
}

题目三:

迷障
n种浓度的万能药水,体积V都相同,浓度则分别为Pi%,配置出浓度不大于 W%的药水—得到最大体积
输入:
一个整数C,表示测试数据的组数(输入方式)
每组测试数据包含2行,首先一行给出三个正整数n,V,W(1<=n,V,W<=100);
接着一行是n个整数,表示n种药水的浓度Pi%(1<=Pi<=100)。
输出:
对于每组测试数据,请输出一个整数和一个浮点数;
其中整数表示解药的最大体积,浮点数表示解药的浓度(四舍五入保留2位小数);
如果不能配出满足要求的的解药,则请输出0 0.00
思路:
选取浓度最低的来配置,体积相同
混合液体的浓度 = (浓度和)/n
代码:

#define _CRT_SECURE_NO_DEPRECATE
/*
贪心算法:配置药水  (a+b)/2
*/
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
    int C;
    scanf("%d", &C);
    while (C-->0)
    {
        int n, v, w;
        int p[100] = {0};
        scanf("%d%d%d", &n, &v, &w);
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &p[i]);
        }
        sort(p, p + n);
        int curP = 0; //当前浓度
        int curV = 0; //当前体积个数
        for (int i = 0; i < n; i++)
        {
            //由于浓度可能是double类型的数据,判断起来容易出错,所以我们反向思考,将除以改成乘以
            if ((curP + p[i]) <= w*(curV+1))
            {
                curP +=p[i];
                curV+=1;
            }
            else
            {
                break;
            }
        }
        if (curV == 0)
            printf("0 0.00\n");
        else
            printf("%d %.2lf\n", curV*v, curP*1.0/(100*curV)); //这里要用小数表示,所以要除以(100*curV)
    }
    return 0;
}

题目四:

修理墙壁–使用尽可能小的木板
The shape of the crack is a rectangle with the size of 1×L (in inch)
the width of all blocks were 1 inch.
样例输入:
5 3
3 2 1
5 2
2 1
样例输出:
2
impossible
代码:

 #define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<algorithm>
using namespace std;
bool cmp(int a, int b)
{
    return a > b;
}
int main()
{
    int L,n;
    int buf[601];
    while (scanf("%d%d", &L,&n) != EOF)
    {
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &buf[i]);
        }
        sort(buf, buf + n,cmp);//降序排列
        int current = 0;
        int res = 0;
        for (int i = 0; i < n; i++)
        {
            if (current < L)
            {
                current += buf[i];
                res += 1;
            }
            else 
            {
                break;
            }
        }
        if (current < L)
            printf("impossible\n");
        else
            printf("%d\n", res);
    }
    return 0;
}

题目五:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值