zoukankan      html  css  js  c++  java
  • 初识贪心

    一、简单贪心

    贪心法是求解一类最优问题的方法,它总是考虑当前状态下局部最优(或较优)的策略,来使全局的结果达到最优或者较优。

    如果在想到某个似乎可行的策略,并且自己无法举出反例,那么就勇敢的去实现它。

    输入格式
    每个输入包含1个测试用例。每个测试用例先给出个不超过 1000 的正整数N表示月
    饼的种类数以及不超过500 (以万吨为单位)的正整数D表示市场最大需求量,随后一行给
    出N个正数表示每种月饼的库存量(以万成为单位),最后行给出N个正数表示每种月饼
    的总售价(以亿元为单位)。数字间以空格分隔。
    输出格式
    对每组测试用例,在行中输出最大收益,以亿元为单位并精确到小数点后两位。
    输入样例
    3 20
    18 15 10
    75 72 45
    输出样例
    94.50
    题意
    现有月饼需求量为D,已知n种月饼各自的库存量和总售价,问如何销售这些月饼,使
    得可以获得的收益最大。求最大收益。
    思路
    步骤1:这里采用“总是选择单价最高的月饼出售,可以获得最大的利润”的策略。
    因此,对每种月饼,都根据其库存量和总售价来计算出该种月饼的单价。
    之后,将所有月饼按单价从高到低排序。
    步骤2:从单价高的月饼开始枚举。
    ①如果该种月饼的库存量不足以填补所有需求量,则将该种月饼全部卖出,此时需求量
    减少该种月饼的库存量大小,收益值增加该种月饼的总售价大小。
    ②如果该种月饼的库存量足够供应需求量,则只提供需求量大小的月饼,此时收益值增
    加当前需求量乘以该种月饼的单价,而需求量减为0。
    这样,最后得到的收益值即为所求的最大收益值。
    策略正确性的证明:假设有两种单价不同的月饼,其单价分别为a和b (a<b)。如果当
    前需求量为K,那么两种月饼的总收入分别为aK与bK,而aK < bK显然成立,因此需要出
    售单价更高的月饼。
    注意点
    ①月饼库存量和总售价可以是浮点数(题目中只说是正数,没说是正整数),需要用
    double型存储。对于,总需求量D虽然题目说是正整数,但是为了后面计算方便,也需要定
    义为浮点型。很多得到“答案错误”的代码都错在这里。
    2当月饼库存量高于需求量时,不能先令需求量为0,然后再计算收益,这会导致该步收益为0,

    3.当月饼库存量高于需求量时,要记得将循环中断,否则出错。

    参考代码:

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 
     5 struct mooncake{
     6     double store; //库存量
     7     double sell; //总售价
     8     double price; //单价 
     9 }cake[1010];
    10 
    11 bool cmp(mooncake a,mooncake b)
    12 {
    13     //按单价从高到低排序
    14     return a.price>b.price; 
    15 }
    16 
    17 int main()
    18 {
    19     int n,D;  //月饼种类数和市场需求量
    20     cin >> n >> D;
    21     for(int i=0;i<n;i++)  //输入每种月饼的库存量 
    22     {
    23         cin >> cake[i].store;
    24      } 
    25      for(int j=0;j<n;j++)  //输入每种月饼的总售价并计算单价
    26      {
    27          cin >> cake[j].sell;
    28          cake[j].price=cake[j].sell/cake[j].store;
    29       } 
    30       sort(cake,cake+n,cmp); //单价从高到低排序
    31       double w = 0; //收益
    32        for(int i=0;i<n;i++)
    33        {
    34            if(cake[i].store <= D)  //如果需求量高于库存量
    35            {
    36                D -= cake[i].store;  //第i种月饼全部卖出
    37                w += cake[i].sell; 
    38             } 
    39             else  //库存量高于需求量 
    40             {
    41                 w += cake[i].price * D; //卖出剩余需求量的月饼
    42                 break; 
    43             }
    44         } 
    45         printf("%.2f
    ",w);
    46     return 0;
    47 }

    [PAT B1023]组个最小数

    题目描述
    给定数字0-9各若干个。可以任意顺序排列这些数字,但必须全部使用。目标是使得最
    后得到的数尽可能小(注意: 0不能做首位)。例如,给定两个0、 两个1、三个5和一个8,
    得到的最小的数就是10015558.
    现给定数字,请编写程序输出能够组成的最小的数。
    输入格式
    每个输入包含1个测试用例。每个测试用例在一行中给出 十个非负整数,顺序表示所相
    有数字0、数字....数字9的个数。整数间用一个空格分隔。 十个数字的总个数不超过50.
    且至少拥有一个非0的数字。
    输出格式
    在一行中输出能够组成的最小的数。
    输入样例
    2200030010
    输出样例
    10015558
    思路
    策略是:先从1~9中选择个数不为0的最小的数输出,然后从0~ 9输出数字,每个数
    字输出次数为其剩余个数。
    以样例为例,最高位为个数不为0的最小的数1,此后1的剩余个数减1 (由2变为1)。
    接着按剩余次数(0剩余两个,1剩余一个,5出现三个,8出现一个)依次输出所有数。
    策略正确性的证明:首先,由于所有数字都必须参与组合,因此最后结果的位数是确定
    的。然后,由于最高位不能为0,因此需要从[1,9]中选择最小的数输出(如果存在两个长度
    相同的数的最高位不同,那么定是最高位小的数更小)。 最后,针对除最高 位外的所有位,
    也是从高位到低位优先选择[0, 9]中还存在的最小的数输出。
    注意点
    由于第一位不能是0, 因此第一个数字必须从 1 ~ 9中选择最小的存在的数字,且找到这
    样的数字之后要及时中断循环。
    参考代码

     1 #include<iostream>
     2 using namespace std;
     3 int main()
     4 {
     5     int count[10]; //记录十个数字
     6     for(int i=0;i<10;i++)
     7     {
     8         cin >> count[i];
     9      } 
    10      for(int i=1;i<10;i++)  //从1~9种选择count不为0的最小数字 
    11      {
    12          if(count[i] > 0)
    13          {
    14              cout << i;
    15              count[i]--;
    16              break; //找到一个后就中断 
    17          }
    18      }
    19      for(int i=0;i<10;i++)
    20      {
    21          for(int j = 0;j < count[i]; j++)
    22          cout << i;
    23      }
    24      cout << endl;
    25     return 0;
    26 }

     二、区间贪心

    区间不相交问题

    给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间两两没有交集;

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 const int maxn = 110;
     5 struct Interval{
     6     int x,y; //开区间左右端点 
     7 }I[maxn];
     8 bool cmp(Interval a,Interval b)
     9 {
    10     if(a.x != b.x)
    11     return a.x > b.x;
    12     else
    13     return a.y < b.y;
    14 }
    15 
    16 int main()
    17 {
    18     int n;
    19     while(cin >> n)
    20     {
    21         for(int i = 0;i < n; i++)
    22         cin >> I[i].x >> I[i].y;
    23         sort(I,I+n,cmp); //把区间排序
    24         //ans记录不想交区间个数,lastX记录上一个被选中区间的左端点
    25         int ans = 1;
    26         int lastX = I[0].x;
    27         for(int i = 1;i < n;i++)
    28         {
    29             if(I[i].y <= lastX)
    30             {
    31                 lastX = I[i].x;
    32                 ans ++;
    33             }
    34          } 
    35          cout << ans << endl;
    36     }
    37     return 0;
    38 }
  • 相关阅读:
    Saltstack module gem 详解
    Saltstack module freezer 详解
    Saltstack module firewalld 详解
    Saltstack module file 详解
    Saltstack module event 详解
    Saltstack module etcd 详解
    Saltstack module environ 详解
    Saltstack module drbd 详解
    Saltstack module dnsutil 详解
    获取主页_剥离百度
  • 原文地址:https://www.cnblogs.com/wlyperfect/p/12526905.html
Copyright © 2011-2022 走看看