贪心算法小结

news2025/7/11 14:58:44

A-金银岛

  某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同,分别为n 1, n 2, ... , n s,同时每个种类的金属总的价值也不同,分别为v 1,v 2, ..., v s。KID想一次带走价值尽可能多的金属,问他最多能带走价值多少的金属。注意到金属是可以被任意分割的,并且金属的价值和其重量成正比。

Input

   第1行是测试数据的组数k,后面跟着k组输入。 
  每组测试数据占3行,第1行是一个正整数w (1 <= w <= 10000),表示口袋承重上限。第2行是一个正整数s (1 <= s <=100),表示金属种类。第3行有2s个正整数,分别为n 1, v 1, n 2, v 2, ... , n s, v s分别为第一种,第二种,...,第s种金属的总重量和总价值(1 <= n i <= 10000, 1 <= v i <= 10000)。 

Output

  k行,每行输出对应一个输入。输出应精确到小数点后2位。

Sample Input

2
50
4
10 100 50 30 7 34 87 100
10000
5
1 43 43 323 35 45 43 54 87 43

Sample Output
171.93
508.00
  贪心问题,要注意题中说金属是可以任意分割的,且金属的价值和其质量成正比。所以要求出单位质量金属的价值,再排序。还有就是输出格式,要输出小数点后两位。代码如下:
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
int const max_n = 200;
struct node{
    int n,v;
    double p;
}s[max_n];
bool cmp(node a,node b)
{
    return a.p>b.p;
}
int main()
{
    int k;
    scanf("%d",&k);
    while(k--)
    {
        int w=0,S;
        double ans=0;
        scanf("%d",&w);
        scanf("%d",&S);
        for(int i=0;i<S;i++)
        {
            cin>>s[i].n>>s[i].v;
            if (s[i].n < 1 || s[i].n>10000 || s[i].v < 1 || s[i].v>10000)return 0;
            s[i].p=double(s[i].v)/s[i].n;
        }
        sort(s,s+S,cmp);
        for(int i=0;i<S;i++)
        {
            if(w>=s[i].n)
            {
                w-=s[i].n;
                ans+=s[i].v;
            }
            else {
                ans+=w*s[i].p;
                w=0;
            }
            if(w==0)break;
        }
        printf("%.2f\n",ans);
    }
    return 0;
}

B - Tian Ji -- The Horse Racing

Here is a famous story in Chinese history. 

That was about 2300 years ago. General Tian Ji was a high official in the country Qi. He likes to play horse racing with the king and others. 

Both of Tian and the king have three horses in different classes, namely, regular, plus, and super. The rule is to have three rounds in a match; each of the horses must be used in one round. The winner of a single round takes two hundred silver dollars from the loser. 

Being the most powerful man in the country, the king has so nice horses that in each class his horse is better than Tian's. As a result, each time the king takes six hundred silver dollars from Tian. 
Tian Ji was not happy about that, until he met Sun Bin, one of the most famous generals in Chinese history. Using a little trick due to Sun, Tian Ji brought home two hundred silver dollars and such a grace in the next match. 
It was a rather simple trick. Using his regular class horse race against the super class from the king, they will certainly lose that round. But then his plus beat the king's regular, and his super beat the king's plus. What a simple trick. And how do you think of Tian Ji, the high ranked official in China? 

Were Tian Ji lives in nowadays, he will certainly laugh at himself. Even more, were he sitting in the ACM contest right now, he may discover that the horse racing problem can be simply viewed as finding the maximum matching in a bipartite graph. Draw Tian's horses on one side, and the king's horses on the other. Whenever one of Tian's horses can beat one from the king, we draw an edge between them, meaning we wish to establish this pair. Then, the problem of winning as many rounds as possible is just to find the maximum matching in this graph. If there are ties, the problem becomes more complicated, he needs to assign weights 0, 1, or -1 to all the possible edges, and find a maximum weighted perfect matching... 
However, the horse racing problem is a very special case of bipartite matching. The graph is decided by the speed of the horses -- a vertex of higher speed always beat a vertex of lower speed. In this case, the weighted bipartite matching algorithm is a too advanced tool to deal with the problem. 
In this problem, you are asked to write a program to solve this special case of matching problem.

Input

The input consists of up to 50 test cases. Each case starts with a positive integer n ( n<=1000) on the first line, which is the number of horses on each side. The next n integers on the second line are the speeds of Tian's horses. Then the next n integers on the third line are the speeds of the king's horses. The input ends with a line that has a single `0' after the last test case.

Output

For each input case, output a line containing a single number, which is the maximum money Tian Ji will get, in silver dollars.

Sample Input

3 92 83 71 95 87 74 2 20 20 20 20 2 20 19 22 18 0
Sample Output
200
0
0
  题目大意:前面讲的是田忌赛马的故事,本题是故事套路的延伸,最多进行50个样例测试,第一行输入双方拥有的马匹数,第二行输入田忌的马匹的速度,第三行输入齐王的马匹速度,
马匹间两两进行赛跑,输的一方要给赢得一方200银元。输出田忌能赢或输多少银元。
  思路:依旧是使用贪心算法,首先对马匹速度进行排序,不断选取最优解,直至解决问题 。那么最优解是什么呢?两匹马进行赛跑,只有三种结果,田忌胜,齐王胜,平局;所以要尽
可能使用田忌的慢马消耗齐王的快马,从双方的慢马开始比较,若田忌的慢马比齐王的慢马快,双方用当前最慢的马匹进行赛跑,田忌胜场加一;反之使用田忌当前的慢马与齐王当前最快的
马进行比赛,田忌负场加一;如果双方此时最慢的马匹速度相等,可以分为两种情况,一:若此时田忌最快的马比齐王最快的马快,使用双方最快的马赛跑,田忌胜场加一,二:使用田忌此
时最慢的马与齐王最快的马赛跑,田忌负场加一。这样能最大程度削弱齐王的马匹优势。代码如下:
#include <iostream>
#include <algorithm>
#include <string.h>
#define LL long long
const int max_n=1002;
using namespace std;
int tian[max_n];
int king[max_n];
bool cmp(int a,int b)
{
    if(a==b)return a;
    return a>b;
}
int main()
{
    int k=50;
    while(k--)
    {
        int n;
        scanf("%d",&n);
        if(n==0)break;
        for(int i=0;i<n;i++)scanf("%d",&tian[i]);
        for(int i=0;i<n;i++)scanf("%d",&king[i]);
        sort(tian,tian+n);
        sort(king,king+n);
        int j=0,t=0;
        int tb=0,tend=n-1;
        int kb=0,kend=n-1;
        for(;tb<=tend;)
        {
            if(tian[tb]>king[kb])
            {
                tb++;
                kb++;
                j++;
            }
            else if(tian[tb]<king[kb])
            {
                tb++;
                kend--;
                t++;
            }
            else{
                if(tian[tend]>king[kend])
                {
                    tend--;
                    kend--;
                    j++;
                }
                else {
                    if(tian[tb]<king[kend])t++;
                    kend--;
                    tb++;
                }
            }
        }
        n=j-t;
        printf("%d\n",n*200);
        memset(tian,0,sizeof(tian));
        memset(king,0,sizeof(king));
    }
    return 0;
}

C - 最小新整数

 给定一个十进制正整数n(0 < n < 1000000000),每个数位上数字均不为0。n的位数为m。
现在从m位中删除k位(0<k < m),求生成的新整数最小为多少?
例如: n = 9128456, k = 2, 则生成的新整数最小为12456

Input

第一行t, 表示有t组数据; 
接下来t行,每一行表示一组测试数据,每组测试数据包含两个数字n, k。

Output

t行,每行一个数字,表示从n中删除k位后得到的最小整数。

Sample Input

2
9128456 2
1444 3
Sample Output
12456
1
  思路:数据可以用string来输入输出,这样可以避免来回转换类型出现的问题。依旧是贪心问题,最优解为:若a[i]>a[i+1](注意边界),则删除a[i];即从输入的数高位开始比较,因为输入
到了字符串中,所以自string a[0]开始遍历,没当其高位数比低位数大时,删除高位字符,删除使用a.erase(a.find(a[i]),1),删除一次计数变量+1,当计数变量与要删除的k值相等时或循环
结束后跳出循环;这时有两种情况,一:已经删够两位了,此时直接输出删后的string即可,二:还没有删除够k位(因为输入的数自高位到低位可能是递增的),此时找到剩余串中的最大值并删除,删除够
k位即可。代码如下:
 
#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
using namespace std;

string compare(string a, int k)
{

    int b = 0;
    for (int i = 0; i < a.length(); i++)
    {
        if (a[i] > a[i + 1]) {a.erase(a.find(a[i]), 1); b++;}
        if (b == k)break;
    }
    int t = k - b;
    if (t != 0)
    {
        while (t--)
        {
            char td='0';
            for (int i = 0; i < a.length(); i++)
            {
                td = max(td, a[i]);
            }
            a.erase(a.find(td), 1);
        }
    }
    return a;
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        string n;
        int k;
        cin >> n;
        scanf("%d", &k);
        string s = compare(n, k);
        cout << s << endl;
    }
    return 0;
}
 

 D-Allowance

作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴。FJ有一套硬币N种(1≤N≤20)不同的面额,每枚硬币是所有比他小的硬币面值的倍数,例如1美分硬币、5美分硬币、10美分硬币和50美分硬币。使用这些硬币,FJ每周至少给Bessie C(1 <= C <=100000000)美分。请你计算他最多能给Bessie几周

Input

* 第一行N 、 C 

* 第 2..N+1行: 硬币价值 V (1 <= V <= 100,000,000) 和数量 B (1 <= B <= 1,000,000)

Output

* 使用这些硬币,每周至少给C美分的前提下的最多周数

Sample Input

3 6
10 1
1 100
5 120

Sample Output

111

Hint


输出提示 
FJ给Bessie 10美分一周;给Bessie 5美分和1美分一百周;给Bessie 两枚5美分十周

  思路:题中问最多能给多少个星期,也就是用有限的钱,让Bessie干最长时间的工(可以多给钱,但一定不能少给,不然Bessie就罢工了)。首先排序,这题的处理分为两个阶段,一:当该货币的价值大于最低津贴时,每次付一张该货币即可,计数器加上该价值货币的数量。直到货币价值低于最低津贴时,第二阶段开始了。二:此时,应该想办法使用最少的货币数量去支付津贴,那就优先使用最大的货币去多次支付,直到与剩余需支付津贴低于该货币价值,而不足部分,由低价值货币补充,并且应该从价值最低的货币开始补充(这样最可能使支付的钱刚好与津贴相等),直到已经足够支付津贴,计数器加一(要注意每使用一次某种货币,其数量要减一);开始下一轮。当FJ剩余的钱不足以支付一周的最低津贴时,此时计数器大小为最多周数。代码如下:

  

#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
struct node {
    int v, b;//货币价值,数量
}num[22];//货币种类最多20种
bool cmp(node a, node b)//定义结构体排序方法
{
    return a.v > b.v;
}
int main()
{
    int n, c, ans = 0;
    scanf("%d %d", &n, &c);
    for (int i = 0; i < n; i++)
    {
        scanf("%d %d", &num[i].v, &num[i].b);
    }
    sort(num, num + n, cmp);//降序排列
    int k = 0;
    for (k=0; k < n; k++)
    {
        if (num[k].v >= c)//当货币价值大于津贴时
        {
            ans += num[k].b;
        }
        else break;
    }
    bool judge = true;
    while(judge){
        judge = false;
        int s = c;
        for (int i = k; i < n; i++)//自货币价值小于津贴的位置开始,向更小的遍历
        {
            while (num[i].b > 0 && num[i].v < s)
            {//使用尚未支付完的货币中的价值最大的支付,且尽量不支付超过津贴的钱
                s -= num[i].v;
                num[i].b--;
            }
        }
        for (int j = n - 1; j >= k; j--)
        {//优先使用价值小货币,补齐尾款,尽可能不多付钱。
            while (s > 0 && num[j].b > 0)
            {
                s -= num[j].v;
                num[j].b--;
            }
        }
        if (s<=0)//通过两边交叉付款后,若已经付清津贴,则计数器加1
        {
            judge = true;
            ans++;
        }
    }
    printf("%d", ans);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/8755.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ffmpeg视频编解码 demo初探(一)(包含下载指定windows版本ffmpeg)分离视频文件中的视频流每一帧YUV图片

参考文章1&#xff1a;YUV数据流编码成H264 参考文章2&#xff1a;【FFmpeg编码实战】&#xff08;1&#xff09;将YUV420P图片集编码成H264视频文件 文章目录第一个项目&#xff1a;分离视频文件中的视频流每一张图片弯路步入正轨下载官方编译的ffmpeg4.3&#xff08;win64-g…

SpringFramework:SpringBean的生命周期

SpringFramework&#xff1a;SpringBean的生命周期 文章目录SpringFramework&#xff1a;SpringBean的生命周期一、SpringBean的生命周期1. 实例化 Bean2. 填充属性&#xff08;DI&#xff09;3. 初始化4. 销毁二、BeanDefinition1. 基本概念2. 大致结构3. Spring 构建它的优势…

深度学习必备Python基础知识充电2

一、python中的类 1.1 python中是有内置的数据类型的 intstr 1.2 创建新的数据类型 自定义类来实现这样的功能 二、年轻人的第一个python类 2.1 来尝试一下 # 年轻人的第一个自定义python类class Man:def __init__(self, name):self.name nameprint(initialized Succes…

【优雅的参数验证@Validated】@Validated参数校验的使用及注解详解——你还在用if做条件验证?

Validated参数校验的使用及注解详解你还在用if做条件验证吗&#xff1f;一、优雅的参数验证Validated1.Valid和Validated的用法(区别)2.引入并使用Validated参数验证二、javax.validation.constraints下参数条件注解详解三、自定义条件注解你还在用if做条件验证吗&#xff1f; …

【云原生之K8s】 Pod控制器

文章目录一、Pod控制器及其功用二、控制器的类型1.Deployment2.StatefulSet2.1 StatefulSet的组成2.2 常规service和无头服务区别2.3 示例小结3.DaemonSet4.Job5.CronJob一、Pod控制器及其功用 Pod控制器&#xff0c;又称之为工作负载&#xff08;workload&#xff09;&#x…

【毕业设计】机器视觉火车票识别系统 - python 深度学习

文章目录0 前言1 课题意义1.1 课题难点&#xff1a;2 实现方法2.1 图像预处理2.2 字符分割2.3 字符识别2.3.1 部分实现代码3 实现效果4 最后0 前言 &#x1f525; Hi&#xff0c;大家好&#xff0c;这里是丹成学长的毕设系列文章&#xff01; &#x1f525; 对毕设有任何疑问…

疑似大厂泄露!阿里内部Redis教程笔记,细节点满/效率翻倍

Redis是一个key-value存储系统&#xff0c;是当下互联网公司广泛采用的NoSQL数据库之一&#xff0c;也是Java程序员应知应会的必备技术。 这套笔记教程采用Redis 6.2.1版本&#xff0c;内容由浅入深&#xff0c;循序渐进&#xff0c;从Redis的基本概念开启讲解&#xff0c;内容…

React核心技术浅析

1. JSX与虚拟DOM 我们从React官方文档开头最基本的一段Hello World代码入手: ReactDOM.render(<h1>Hello, world!</h1>,document.getElementById(root) );这段代码的意思是通过 ReactDOM.render() 方法将 h1 包裹的JSX元素渲染到id为“root”的HTML元素上. 除了在…

NVIDIA Grace Hopper架构深度解析

NVIDIA Grace Hopper架构深度解析 NVIDIA Grace Hopper Superchip 架构是第一个真正的异构加速平台&#xff0c;适用于高性能计算 (HPC) 和 AI 工作负载。 它利用 GPU 和 CPU 的优势加速应用程序&#xff0c;同时提供迄今为止最简单、最高效的分布式异构编程模型。 科学家和工程…

Python~Pandas 小白避坑之常用笔记

Python~Pandas 小白避坑之常用笔记 提示&#xff1a;该文章仅适合小白同学&#xff0c;如有错误的地方欢迎大佬在评论处赐教 文章目录Python~Pandas 小白避坑之常用笔记前言一、pandas安装二、数据读取1.读取xlsx文件2.读取csv文件三、重复值、缺失值、异常值处理、按行、按列剔…

pytest allure 生成报告过程

allure 下载地址&#xff1a;Releases allure-framework/allure2 GitHub 下载好后配置环境变量执行&#xff1a; allure --version 看见版本号就算配置成功了 pytest allure 生成报告过程 allure添加测试类名&#xff0c;方法名&#xff0c;步骤&#xff1a; allure.fea…

【附源码】计算机毕业设计JAVA教学成果管理平台录像演示

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven Vue 等等组成&#xff0c;B/…

教你一招轻松搞定mp3格式转换

第一种&#xff1a;ncm转mp3 经常使用网易云音乐的朋友应该会发现&#xff0c;网易云VIP音乐下载后&#xff0c;有些音乐是ncm格式的&#xff0c;无法导入PR或者一些编辑软件。 解决方法如下&#xff1a; 利用在线网站处理——Convertio 第一步&#xff1a;打开谷歌浏览器客户端…

9家美发连锁店老板一天剪辑1000个视频,用呆头鹅批量剪辑软件剪

1.1呆头鹅批量剪辑软件核心优势 01.我们的产品是经过市场考验的&#xff0c;像有结果的人学习&#xff0c;买有结果的产品。 02.3年的打磨&#xff0c;更新和删除了200多个模块 03.100多次持续优化更新 04.10000个公司和工作室和个人的使用和建议。 05.一个用户至少做出100…

磁盘有空间但无法创建文件

面试原题 我们去面试的时候,面试官通常会问一个问题, “小伙子,你在这些年的工作中,遇到过什么棘手的问题没有? 面试官问这个问题,无非想知道以下几件事情 你有没有过处理疑难问题的经验你解决问题的思路和能力如何你是怎么解决的你解决完这个问题有哪些收获 面试错误示范 …

Java生成验证码+动态分析技术+【实训10】HTML信息隐藏(信息安全技术作业)

Java生成验证码 第1关&#xff1a;使用Servlet生成验证码 任务要求参考答案评论 任务描述相关知识 为什么要有验证码&#xff0c;什么是验证码如何使用Servlet生成验证码编程要求测试说明任务描述 本关任务&#xff1a;使用servlet生成验证码。 相关知识 验证码在我们登陆…

硬链接及软连接引出的inode

inode定义 inode是linux系统中用作数据索引的标识符。简单来说&#xff0c;inode指示了一个文件的基本信息&#xff0c;如inode编号、修改时间、文件的位置等。 如同一本书的目录&#xff0c;会直接告诉你想看的章节是在第几页。不同的是&#xff0c;书是以页为单位的&#x…

软考 - 数据结构与算法

数据结构 线性结构 线性表 存储结构 顺序存储&#xff1a;用一组地址连续的存储单元 依次存储线性表中的数据元素&#xff0c;使得逻辑上相邻的元素物理上也相邻。 链式存储&#xff1a;存储各数据元素的结点的地址并不要求是连续的&#xff0c;数据元素逻辑上相邻&#xff…

提升Mac运行速度的三大方法

任何一部电子设备在使用多年之后都会出现性能下降的问题&#xff0c;苹果的Mac计算机自然也不例外。当你发现Mac运行缓慢&#xff0c;因为有太多文件或缓存垃圾将Mac的运行速度拖了下来。 要想提高生活和工作效率&#xff0c;必须对Mac进行优化&#xff0c;提升一下Mac 的使用性…

全业务链管理平台Odoo

什么是 Odoo ? Odoo 是一款非常容易使用又完全集成的商业应用&#xff0c;是一站式全业务链管理平台。 docker cli 安装 本项目涉及到 2 个容器&#xff0c;之前我们在下面&#x1f447;这些文章中 开源的看板管理工具Wekan类Trello的看板软件Planka群晖上安装MediaWiki的简…