贪心练习

题目链接
本套题比较难的是C,B和F需要思考一下,其它简单。
A.看电视
题解:很自然可以想到,要么按照开始时间排序,要么按照结束时间排序。按开始时间排,可能最早开始的会占后面开始的两个节目,故排除此方法。所以按照结束时间升序排即可,每次选择最早结束的,可以得到最多的节目。

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int s, e;
}a[110];
bool cmp(node a, node b)
{
    return a.e < b.e;
}
int main()
{
    int n, i;
    while (~scanf("%d", &n) && n){
        for (i = 0; i < n; i++)
            scanf("%d%d", &a[i].s, &a[i].e);
        sort(a, a + n, cmp);
        int cnt = 0, last_end = 0;
        for (i = 0; i < n; i++)
            if (a[i].s >= last_end) cnt++, last_end = a[i].e;
        printf("%d\n", cnt);
    }
}

B. 出租车费
题解:1-4公里2.5元/公里,1-8公里2.25元/公里,再往后每公里费用大于2.25元。所以,每次贪心地选择每辆车坐8公里,剩余路程如果<=4就继续坐下去,否则再坐一辆新的,此方案保证费用最少。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n, i;
    while (~scanf("%d", &n) && n){
        if (n <= 4) printf("10\n");
        else if (n <= 8) printf("%d\n", 10 + (n - 4) * 2);
        else{
            int num = n / 8, rest = n % 8;
            if (!rest) printf("%d\n", num * 18);
            else if (rest <= 4) printf("%.1f\n", num * 18 + rest * 2.4);
            else printf("%d\n", num * 18 + 10 + (rest - 4) * 2);
        }
    }
}

C.To Fill or Not to Fill
题解:首先判断汽车不能到达终点的情况:起点没有加油站;相邻两加油站的距离大于汽车的行驶距离。
然后在汽车的行驶距离内寻找更便宜的加油站:如果有,那么汽车要到这个加油站,判断油量是否足够,够就不加油,不够就加油;如果没有,判断下从当前加油站出发能否到终点,能到计算相应油量,不能就加满油,因为当前加油站其实已经是最便宜的了,加满即可。

#include<bits/stdc++.h>
using namespace std;
struct node
{
    double pri, dis;
}k[510];
bool cmp(node a, node b)
{
    return a.dis < b.dis;//将加油站照位置升序排列
}
int main()
{
    double cmax, d, davg;
    int n, i, j;
    scanf("%lf%lf%lf%d", &cmax, &d, &davg, &n);
    for (i = 0; i < n; i++)
        scanf("%lf%lf", &k[i].pri, &k[i].dis);
    sort(k, k + n, cmp);
    k[n].dis = d;
    if (k[0].dis){//起点没有加油站
        printf("The maximum travel distance = 0.00\n");
        return 0;
    }
    double res = 0, curoil = 0;
    double maxdis = cmax * davg;
    for (i = 0; i < n; i++){
        double curpos = k[i].dis;
        if (curpos + maxdis < k[i + 1].dis){//相邻加油站不能到达
            printf("The maximum travel distance = %.2lf\n", curpos + maxdis);
            break;
        }
        if (i) curoil -= (k[i].dis - k[i - 1].dis) / davg;
        bool ischeap = 0;
        for (j = i + 1; j < n; j++){//行驶范围内找更便宜的加油站
            double curdis = k[j].dis - k[i].dis;
            if (curdis > maxdis) break;
            if (k[j].pri < k[i].pri){
                double temp = curoil;//当前油量
                curoil = curdis / davg;//需要油量
                if (temp < curoil) res += (curoil - temp) * k[i].pri;
                else curoil = temp;
                ischeap = 1;
                break;
            }
        }
        if (!ischeap){//没便宜站
            if (curpos + maxdis >= d){//能到终点
                res += ((d - curpos) / davg - curoil) * k[i].pri;
                printf("%.2lf\n", res);
                break;
            }
            else{//不能到终点
                res += (cmax - curoil) * k[i].pri;
                curoil = cmax;
            }
        }
    }
}

D.Repair the Wall
题意:用若干个可切割的小矩形合成一个大距形,问最少需要多少个小矩形。
题解:每次贪心地选取尺寸最大的小矩形即可,多出来的切割掉。

#include<bits/stdc++.h>
using namespace std;
int a[610];
int main()
{
    int l, n, i;
    while (~scanf("%d%d", &l, &n)){
        for (i = 0; i < n; i++)
            scanf("%d", &a[i]);
        sort(a, a + n);
        long long sum = 0;
        bool flag = 0;
        int res = 0;
        for (i = n - 1; i >= 0; i--){
            sum += a[i], res++;
            if (sum >= l){
                flag = 1;
                printf("%d\n", res);
                break;
            }
        }
        if (!flag) printf("impossible\n");
    }
}

E.FatMouse’s Trade
题意:有m个猫食,fi个猫食可以换ji个java豆,问最多能换多少个java豆。
题解:每次贪心地选取ji/fi最大的一组即可。

#include<bits/stdc++.h>
using namespace std;
struct node
{
    double a, b;
}k[1010];
bool cmp(node e, node f)
{
    return e.a * f.b > f.a * e.b;
}
int main()
{
    int m, n, i;
    while (~scanf("%d%d", &m, &n)){
        if (m == -1 && n == -1) break;
        for (i = 0; i < n; i++)
            scanf("%lf%lf", &k[i].a, &k[i].b);
        sort(k, k + n, cmp);
        double res = 0;
        for (i = 0; i < n; i++){
            if (m >= k[i].b){
                res += k[i].b * k[i].a / k[i].b;
                m -= k[i].b;
            }
            else{
                res += m * k[i].a / k[i].b;
                m = 0;
            }
        }
        printf("%.3lf\n", res);
    }
}

F.迷瘴
题解:由题意得,(p1v+p2v+…+piv)/ iv=(p1+p2+…+pi)/i <= w,这样做能比较有效地避免误差。

#include<bits/stdc++.h>//µΘΜε»ύ
using namespace std;
double p[110];
int main()
{
    int t, n, v, w, i;
    scanf("%d", &t);
    while (t--){
        scanf("%d%d%d", &n, &v, &w);
        for (i = 0; i < n; i++)
            scanf("%lf", &p[i]);
        sort(p, p + n);
        if (p[0] > w) printf("0 0.00\n");//排序后,浓度只能变大不能变小
        else{
            double tempp = p[0];
            int tempv = v;
            for (i = 1; i < n; i++){
                tempp += p[i];
                if (tempp / (i + 1) <= w) tempv += v;
                else{
                    tempp -= p[i];
                    break;
                }
            }
            printf("%d %.2lf\n", tempv, tempp / i / 100);
        }
    }
}

G.找零钱

#include<bits/stdc++.h>
using namespace std;
int a[10] = {50, 20, 10, 5, 1};
int b[10];
int main()
{
    int n, i;
    while (~scanf("%d", &n)){
        for (i = 0; i < 5; i++){
            b[i] = n / a[i];
            n %= a[i];
        }
        int p = 0;
        for (i = 0; i < 5; i++){
            if (b[i]){
                if (p) printf("+");
                printf("%d*%d", a[i], b[i]);
                p++;
            }
        }
        printf("\n");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值