算法_贪心算法

1 装箱问题

在这里插入图片描述
输入样例:

8
60 70 80 90 30 40 10 20

输出样例:

60 1
70 2
80 3
90 4
30 1
40 5
10 1
20 2
5
#include<iostream>
using namespace std;
int main(){
    int N,i,j;
    cin >> N;
    int a[N],b[N]={0},c[N]={0};
    for(i=0;i<N;i++){
        cin >> a[i];
    }
    for(i=0;i<N;i++)
        for(j=0;;j++){
            if(a[i]+b[j]<=100){
                b[j]+=a[i];
                c[i]=j+1;
                break;
            }
        }
    for(i=0;i<N;i++)
        cout << a[i] << " " << c[i]<<endl;
    int max=0;
    for(j=0;j<N;j++){
        if(c[max]<c[j])
            max=j;
    }
    cout<<c[max];
    return 0;
}

2 月饼

月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。

注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有 3 种月饼,其库存量分别为 18、15、10 万吨,总售价分别为 75、72、45 亿元。如果市场的最大需求量只有 20 万吨,那么我们最大收益策略应该是卖出全部 15 万吨第 2 种月饼、以及 5 万吨第 3 种月饼,获得 72 + 45/2 = 94.5(亿元)。

输入格式:
每个输入包含一个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N 表示月饼的种类数、以及不超过 500(以万吨为单位)的正整数 D 表示市场最大需求量。随后一行给出 N 个正数表示每种月饼的库存量(以万吨为单位);最后一行给出 N 个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。

输出格式:
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后 2 位。

输入样例:

3 20
18 15 10
75 72 45

输出样例:

94.50
#include<iostream>
#include<algorithm>
using namespace std;
#define max 1000
double x[max]={0};
struct Moon{
    float w;
    float v;
    float p;
}moon[max];
bool comp(Moon a,Moon b){
    return a.p>=b.p;
}
void input(int n){
    for(int i=1;i<=n;i++){
        cin >> moon[i].w;
    }
    for(int i=1;i<=n;i++){
        cin >> moon[i].v;
        moon[i].p = moon[i].v/moon[i].w;
    }
}
float xs(int N,int D){
    float value=0;
    for(int i=1;i<=N;i++){
        if(D>=moon[i].w){
            value+=moon[i].v;
            D-=moon[i].w;
        }else{
            value+=moon[i].p*D;
            break;
        }
    }
    return value;
}
int main(){
    int N,D;
    float TotalValue=0;
    cin >> N >> D;
    input(N);
    sort(moon+1,moon+N+1,comp);
    TotalValue = xs(N,D);
    printf("%.2f",TotalValue);
}

3 最优合并问题

题目来源:王晓东《算法设计与分析》

给定k 个排好序的序列, 用 2 路合并算法将这k 个序列合并成一个序列。 假设所采用的 2 路合并算法合并 2 个长度分别为m和n的序列需要m+n-1 次比较。试设 计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。 为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。

输入格式:
第一行有 1 个正整数k,表示有 k个待合并序列。 第二行有 k个正整数,表示 k个待合并序列的长度。

输出格式:
输出最多比较次数和最少比较次数。

输入样例:
在这里给出一组输入。例如:

4
5 12 11 2 

输出样例:
在这里给出相应的输出。例如:

78 52
#include<bits/stdc++.h>
using namespace std;

bool cmp(int a, int b){
    return a > b;
}
int main(){
    int N,n;
    cin >> N;
    list<int> L, p;
    for(int i = 0; i < N; i++){
        cin >> n;
        L.push_back(n);
        p.push_back(n);
    }
    int max = 0, min = 0;
    for (int i = 0; i < N - 1; i++){
        L.sort();
        int mark1 = 0;
        for (int i = 0; i < 2; i++){
            mark1 += *L.begin();
            L.pop_front();
        }
        min += mark1-1;
        L.push_back(mark1);
 
        p.sort(cmp);
        int mark2 = 0;
        for (int i = 0; i < 2; i++){
            mark2 += *p.begin();
            p.pop_front();
        }
        max += mark2-1;
        p.push_back(mark2);
    }
    cout << max << " " << min << endl;
    return 0;
}

4 看电影

终于到周末了,明明是特别喜欢看电影。他想在一天内尽量多的看到完整的多部电影。 现在他把他喜欢的电影的播放时间表给你,希望你能帮他合理安排。

输入格式:
输入包含多组测试数据。每组输入的第一行是一个整数n(n<=100),表示明明喜欢的电影的总数。 接下来n行,每行输入两个整数si和ei(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
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct Movie{
    int s;
    int f;
};
int cmp(Movie &a, Movie &b){
    return a.f < b. f;
}
int main(){
    int n;
    while(cin>>n){
        if(n==0){
            break;
        }
        Movie p1[1000];
        for(int i = 0; i < n; i ++){
            cin>>p1[i].s>>p1[i].f;
        }
        sort(p1,p1+n,cmp);
        int sum = 0;
        int num = -1;
        for(int i = 0; i < n ;i ++ ){
            if(p1[i].s >= num){
                sum++;
                num = p1[i].f;
            }
        }
        cout<<sum<<endl;
    }
}


5 喷水装置

长L米,宽W米的草坪里装有n个浇灌喷头。每个喷头都装在草坪中心线上(离两边各W/2米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?

输入格式:
输入包含若干组测试数据。

第一行一个整数T表示数据组数。

每组数据的第一行是整数n、L和W的值,其中n≤10 000。

接下来的n行,每行包含两个整数,给出一个喷头的位置和浇灌半径。

如图1所示的示意图是样例输入的第一组数据所描述的情况。
在这里插入图片描述
输出格式:
对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开还不能浇灌整块草坪,则输出-1。

输入样例:

3
8 20 2
5 3
4 1
1 2
7 2
10 2
13 3
16 2
19 4
3 10 1
3 5
9 3
6 1
3 10 1
5 3
1 1
9 1

输出样例:

6
2
-1

数据范围与提示:
对于100%的数据,n≤15000。

#include<iostream>
#include<algorithm>
#include<cmath>
struct Pen{
    double left;
    double right;
}pen[15000];
int cmp(Pen x,Pen y){
    return x.left<y.left;   //按照左坐标从小到大排列
}
using namespace std;
int main(){
    int N;
    cin >> N;
    while(N--){
        int n;
        cin >> n;
        double w,h;
        cin >> w >> h;
        for(int i=0;i<n;i++){
            double xi,ri;
            cin >> xi >> ri;
            double flag;
            if(ri>h/2)
                flag = sqrt(ri*ri-h*h/4);
            else
                flag = 0.0;
            pen[i].left = xi-flag;
            pen[i].right = xi+flag;
        }
        sort(pen,pen+n,cmp);
        int count = 0;
        double star =0.0,last;  //last记录右交点
        for(int i=0;i<n;i++){
            if(pen[i].left <= star){
                last = pen[i].right;
                while(pen[i].left <= star){
                    last = max(last,pen[i].right);
                    i++;
                    if(i == n)
                        break;
                }
                star = last;    //star记录满足条件的下一个装置的右坐标
                i--;
                count++;
            }
            if(star >= w)
                break;
        }
        if(star >= w)
            cout << count <<endl;
        else
            cout << "-1" <<endl;
    }
    return 0;
}

6 活动选择问题

在这里插入图片描述
输入样例:

11
3 5
1 4
12 14
8 12
0 6
8 11
6 10
5 7
3 8
5 9
2 13

输出样例:

4

样例解释:
安排的4个活动为1 4, 5 7, 8 11和12 14。

#include<iostream>
#include<algorithm>
using namespace std;
typedef struct activity{
    int s;
    int f;
};
int cmp(activity &a, activity &b){
    return a.f < b. f;
}
int main(){
    int n;
    cin >> n;
    activity p1[1000];
    for(int i = 0; i < n; i ++){
        cin>>p1[i].s>>p1[i].f;
    }
    sort(p1,p1+n,cmp);
    int sum = 0;
    int num = -1;
    for(int i = 0; i < n ;i ++ ){
        if(p1[i].s >= num){
            sum++;
            num = p1[i].f;
        }
    }
    cout<<sum<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玳宸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值