贪心算法

---------------2017-04-22----------------------

什么是贪心算法呢?所谓贪心算法是指,在对问题求解时,总是做出在当前看来最好的选择。也就是说,不从整体最优解出发来考虑,它所做出的仅是在某种意义上的局部最优解。

贪心策略适用的前提是:局部最优策略能导致产生全局最优解。
    实际上,贪心算法适用的情况很少。选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。

21.FatMouse' Trade (九度oj)

题目描述:
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.
样例输入:
5 3
7 2
4 3
5 2
20 3
25 18
24 15
15 10
-1 -1
样例输出:
13.333
31.500

解题思路:为了买最多量的东西,首先买性价比最高的,依次往后.

/*!
 * Description:
 * author scictor <scictor@gmail.com>
 * date 2018/6/28
 */

#include <bits/stdc++.h>
using namespace std;
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
#define debug(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl

struct buy{
    double j;//total weight of this kind
    double f;//total value of this kind
    double ration;
//    bool operator < (const buy &rt) const // overload <,i.e this.ration < rt.ration
//    {
//        return ration < rt.ration;
//    }
}buys[1001];

int main(){
    double mny;
    int n;
    while(scanf("%lf%d", &mny, &n) != EOF)
    {
        memset(&buys, 1001, 0x00); //debug(mny);debug(n);
        if(mny == -1 && n == -1) break;
        for (int i = 0; i < n; i++)
        {
            scanf("%lf%lf", &buys[i].j, &buys[i].f);//cout << buys[i].j << ' ' << buys[i].f;
            buys[i].ration = buys[i].j / buys[i].f;
        }
//        for (int i = 0; i < n; i++) {
//            printf("%lf %lf %lf ", buys[i].j, buys[i].f, buys[i].ration);
//            debug(__LINE__);
//        }
        //sort(buys, buys+n); // default use <, so after sort, arr in asc. not ok.
        //for(int i = 0; i < n; i++) cout << buys[i].ration << ' ';
        sort(buys, buys+n, [](const buy& lb, const buy& rb){
            return lb.ration > rb.ration;
        }); // 降序desc
//        for (int i = 0; i < n; i++) {
//            printf("%lf %lf %lf ", buys[i].j, buys[i].f, buys[i].ration);
//            debug(__LINE__);
//        }
        double weight = 0;
        for (int i = 0; i < n && mny > 0; i++)
        {
            if(mny > buys[i].f)
            {
                weight += buys[i].j; //debug(weight);
                mny -= buys[i].f;    //debug(mny);
            }else if(mny == buys[i].f)
            {
                weight += buys[i].j; //debug(weight);
                mny -= buys[i].f;    //debug(mny);
                break;
            }else if(mny < buys[i].f)
            {
                weight += buys[i].ration * mny; //debug(weight);
                mny = 0;                        //debug(mny);
                break;
            }
        }
        printf("%.3lf
", weight); //cout << weight << endl;
    }
    return 0;
}

22.今年暑假不 AC (九度oj)

题目描述:
“ 今 年 暑 假 不 AC ? ”“ 是 的 。 ”“ 那 你 干 什 么 呢 ? ”“ 看 世 界 杯 呀 , 笨
蛋! ”“@#$%^&*%...”确实如此,世界杯来了,球迷的节日也来了,估计很多 ACMer
也会抛开电脑,奔向电视作为球迷,一定想看尽量多的完整的比赛,当然,作为
新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记
关心国家大事)、非常 6+7、超级女生,以及王小丫的《开心辞典》等等,假设
你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标
是能看尽量多的完整节目)
输入:
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数
n(n<=100),表示你喜欢看的节目的总数,然后是 n 行数据,每行包括两个数据
Ti_s,Ti_e (1<=i<=n),分别表示第 i 个节目的开始和结束时间,为了简化问题,每
个时间都用一个正整数表示。n=0 表示输入结束,不做处理。
输出:
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输
出占一行。
样例输入:
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
样例输出:
5

problem
 1 #include <stdio.h>
 2 #include <algorithm>
 3 using namespace std;
 4 struct program { //电视节目结构体
 5     int startTime; //节目开始时间
 6     int endTime; //节目结束时间
 7     bool operator < (const program & A) const { //重载小于号,保证sort函数能够按照结束时间升序排列
 8                 return endTime < A.endTime;
 9     }
10 }buf[100];
11 int main () {
12     int n;
13     while (scanf ("%d",&n) != EOF) {
14         if (n == 0) break;
15         for (int i = 0;i < n;i ++) {
16             scanf ("%d%d",&buf[i].startTime,&buf[i].endTime);
17         } //输入
18         sort(buf,buf + n); //按照结束时间升序排列
19         int currentTime = 0 , ans = 0; //记录当前时间变量初始值为0,答案计数初始值为0
20                 for (int i = 0;i < n;i ++) { //按照结束时间升序便利所有的节目
21             if (currentTime <= buf[i].startTime) { //若当前时间小于等于该节目开始时间,那么收看该在剩余节目里结束时间最早的节目
22                         currentTime = buf[i].endTime; //当前时间变为该节目结束时间
23                 ans ++; //又收看了一个节目
24             }
25         }
26         printf("%d
",ans); //输出
27     }
28     return 0;
29 }

类似题目:南阳理工acm oj

14.会场安排问题

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
描述
学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办。小刘的工作就是安排学校小礼堂的活动,每个时间最多安排一个活动。现在小刘有一些活动计划的时间表,他想尽可能的安排更多的活动,请问他该如何安排。
输入
第一行是一个整型数m(m<100)表示共有m组测试数据。
每组测试数据的第一行是一个整数n(1<n<10000)表示该测试数据共有n个活动。
随后的n行,每行有两个正整数Bi,Ei(0<=Bi,Ei<10000),分别表示第i个活动的起始与结束时间(Bi<=Ei)
输出
对于每一组输入,输出最多能够安排的活动数量。
每组的输出占一行
样例输入
2
2
1 10
10 11
3
1 10
10 11
11 20
样例输出
1
2
提示
注意:如果上一个活动在t时间结束,下一个活动最早应该在t+1时间开始
来源
经典题目
上传者
张云聪

problem

 

解答参见

原文地址:https://www.cnblogs.com/guxuanqing/p/6748017.html