贪心算法

贪心策略

  

贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅是在某种意义上的局部最优解。用局部解构造全局解,即从问题的某一个初始解逐步逼近给定的目标,以尽可能快的求得更好的解。当某个算法中的某一步不能再继续前进时,算法停止。

  贪心策略:将问题分成多个子问题;子问题求局部最优解;局部最优解组合成原问题的解。

  Kruskal,Prim算法
  分类:简单贪心  区间贪心

咖啡豆问题 

题目描述
FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean.
The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and requires F[i] pounds of cat food. FatMouse does not have to trade for all the JavaBeans in the room, instead, he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food. Here a is a real number. Now he is assigning this homework to you: tell him the maximum amount of JavaBeans he can obtain.
输入
The input consists of multiple test cases. Each test case begins with a line containing two non-negative integers M and N. Then N lines follow, each contains two non-negative integers J[i] and F[i] respectively. The last test case is followed by two -1’s. All integers are not greater than 1000.
输出
For each test case, print in a single line a real number accurate up to 3 decimal places, which is the maximum amount of JavaBeans that FatMouse can obtain.
样例输入

4 2
4 7
1 3
5 5
4 8
3 8
1 2
2 5
2 4
-1 -1
1
2
3
4
5
6
7
8
9
10
样例输出

2.286
2.500

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

using namespace std;

const int MAXN = 1000;

struct JavaBean{
    double J;   //咖啡豆 
    double F;  //支付 
    double unitPrice;
    
    //运算符重载
    bool operator<(JavaBean bean) const{
        if(unitPrice == bean.unitPrice){
            return F > bean.F;
        }else{
            return unitPrice < bean.unitPrice;
        }    
    } 
};

JavaBean arr[MAXN]; 
int main(){
    int m,n;

    while(scanf("%d%d",&m,&n) != EOF){
        double  res = 0.00;
        
        if(m == -1 && n == -1){
            break;
        }
        //输入
        for(int i = 0;i < n;i++){
            scanf("%lf%lf",&arr[i].J,&arr[i].F);
        }
        //计算单价 
        for(int i = 0;i < n;i++){
            arr[i].unitPrice =  arr[i].F / arr[i].J;
        }
        
        sort(arr,arr+n);
         
        //贪心策略,输出     
        for(int i = 0;i < n;i++){
            if(m <= 0){
                break;
            }else if(m > arr[i].F){
                res += arr[i].J;
                m -= arr[i].F;
            }else{
                int rate = m/arr[i].F;
                res += arr[i].J * rate; 
                m -= arr[i].F * rate;
            }                 
        }
        
        printf("%.3f\n",res);
    }
    
    return 0;
}

背包问题

  

有一组 1 维的物品需要打包进一批同样的箱子中。所有的箱子有完全一样的长度 l 以及每一个物品长度 li<=l. 我们要找到一个最小的数字 q, 使得 :

(1) 每个箱子最多包含两个物品
(2) 每个物品要被包含在 q 个箱子中的一个中
(3) 在箱子中物品的总长度不能超过 l

你的任务是,给定 n 个整数,l,l1,l2….ln, 计算最小的箱子总数 q.

输入格式

第一行包含一个数字 n(1<= n <= 10^5), 表示有几个物品。第二行包含一个整数表示了箱子的长度 l (l<=10000). 接下去的 n 行是表示了每个物品的长度。

输出格式

输出一个整数,表示能够包含所有物品的最小的箱子总数。
提示 :

The sample instance and an optimal solution is shown in the figure below. Items are numbered from 1 to 10 according to the input order.

思考:如果每次选择两个最大的,可能一次性溢出;如果每次挑选两个最小的,可能后面又会溢出,选择的是最大的和最小的,如果首次他们都未通过

  

posted @ 2020-05-14 09:53  天凉好个秋秋  阅读(202)  评论(0编辑  收藏  举报