贪心训练专题一

1:Swan学院社团招新

作者 liaoning
单位 中南林业科技大学涉外学院

Swan学院社团招新,招新宣讲会分散在不同时间段,大一新生小花花想知道自己最多能完整的参加多少个招新宣讲会(参加一个招新宣讲会的时候不能中断或离开)。
【问题说明】这个问题是对几个相互竞争的招新宣讲会活动进行调度,它们都要求以独占的方式使用某一公共资源(小花花)。调度的目标是找出一个最大的相互兼容的活动集合。
活动选择问题就是要选择出一个由互相兼容的问题组成的最大子集合。

【温馨提示】应先将所有的活动按照结束时间升序排列,然后再选择可能的时间组合,并求出最大的组合数,使用qsort()排序函数是一个不错的选择。qsort 的函数原型是:
void qsort(voidbase,size_t num,size_t width,int(__cdeclcompare)(const void*,const void*));
功 能: 使用快速排序例程进行排序 头文件:stdlib.h
参数: 1 待排序数组首地址;2 数组中待排序元素数量;3 各元素的占用空间大小;4 指向函数的指针,用于确定排序的顺序

输入格式:
第一行为n,表示有n个招新宣讲会,接下来n行每行两个整数表示开始时间和结束时间,由从招新会第一天0点开始的小时数表示(24小时制)。 n <= 1000 。

输出格式:
最多参加的招聘会个数。

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

 3  
 9 10  
 10 20  
 8 15  

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

2

代码长度限制
16 KB
时间限制
1000 ms
内存限制
64 MB

解析:根据题意可以抽象出如下图像
在这里插入图片描述
由图像可知我们每次选终点最小的方案一定是最优方案,方案一定小于等于此方案

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

struct node
{
    int x, y;
    bool operator < (const node &a)
    {
        return y < a.y;
    }
}f[N];

int main()
{
    int n;
    while (cin >> n)
    {
        for (int i = 0; i < n; i ++ ) cin >> f[i].x >> f[i].y;

        sort(f,f + n);

        int end = f[0].y;
        int cnt = 1;
        for (int i = 0; i < n - 1; i ++ )
        {
            if(end <= f[i + 1].x)
            {
                end = f[i + 1].y;
                cnt ++;
            }
        }
        cout << cnt << endl;
    }
    return 0;
}

2:看电影

作者 王会勇
单位 河北科技大学

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

输入格式:
输入包含多组测试数据。每组输入的第一行是一个整数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

代码长度限制
16 KB
时间限制
1000 ms
内存限制
32 MB

解析:和第一题同理

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

struct node
{
    int x, y;
    bool operator < (const node &a)
    {
        return y < a.y;
    }
}f[N];

int main()
{
    int n;
    while (cin >> n, n)
    {
        for (int i = 0; i < n; i ++ ) cin >> f[i].x >> f[i].y;

        sort(f,f + n);

        int end = f[0].y;
        int cnt = 1;
        for (int i = 0; i < n - 1; i ++ )
        {
            if(end <= f[i + 1].x)
            {
                end = f[i + 1].y;
                cnt ++;
            }
        }
        cout << cnt << endl;
    }
    return 0;
}

3:多参加活动,生活才精彩

作者 龙兴
单位 贵州工程应用技术学院

小潘今年来到贵工程读大学,大学的生活多姿多彩。大学里面有很多社团,每一个社团都会举办一些活动。小潘是一个积极向上的孩子,想多参加一些活动。我们大家都知道不同的活动有不同的学分。每一个活动有开始时间和结束时间。

明天就是周末啦,每个社团举办活动都会提前把活动开始的时间,活动结束的时间及活动的学分发布在学校的微信公众号上。小潘和你聊起了明天要去参加活动,看到上面有很多活动,他想要参加更多的活动,但是有的活动会冲突,你和小潘一起计算了明天最多可以参加多少个活动,及可以得到多少学分?

输入格式:
第一行,n代表活动的数量。(n<= 100)
第二行开始到n + 1行,每一行都有s,e,f(s活动开始的时间,e活动结束的时间,f活动的分数),s, e, f为正整数,,s,e <= 22,f <=100。

输出格式:
请输出小潘最多可以参加多少个活动,及得到的分数。

输入样例:

5
1 3 5
2 3 5
3 4 5
4 5 5
4 6 5

输出样例:

3 15

代码长度限制
16 KB
时间限制
1000 ms
内存限制
64 MB

解析:和第一题同理

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

struct node
{
    int x, y, z;
    bool operator < (const node &a)
    {
        return y < a.y;
    }
}f[N];

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i ++ ) cin >> f[i].x >> f[i].y >> f[i].z;
    
    sort(f,f + n);
    
    int end = f[0].y;
    int ans = f[0].z, cnt = 1;
    for (int i = 0; i < n - 1; i ++ )
    {
        if(end <= f[i + 1].x)
        {
            end = f[i + 1].y;
            ans += f[i + 1].z;
            cnt ++;
        }
    }
    cout << cnt << ' ' << ans;
    
    return 0;
}

4:装箱问题

作者 DS课程组
单位 浙江大学

假设有N项物品,大小分别为s1、s2 、…、si 、…、sN,其中si 为满足1≤si ≤100的整数。要把这些物品装入到容量为100的一批箱子(序号1-N)中。装箱方法是:对每项物品, 顺序扫描箱子,把该物品放入足以能够容下它的第一个箱子中。请写一个程序模拟这种装箱过程,并输出每个物品所在的箱子序号,以及放置全部物品所需的箱子数目。

输入格式:
输入第一行给出物品个数N(≤1000);第二行给出N个正整数si(1≤si ≤100,表示第i项物品的大小)。
输出格式:
按照输入顺序输出每个物品的大小及其所在的箱子序号,每个物品占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

代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

解析:直接根据题目进行模拟物品装进箱子的过程,如果装不下,就新添加一个箱子

在这里插入图片描述

#include <iostream>

using namespace std;

const int N = 1010;

int n, idx;
int f[N], a[N];

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++ ) cin >> a[i];
    
    for (int i = 0; i < n; i ++ )
    {
        int j = 0;
        for ( ;j < idx; j ++ )
            if(f[j] + a[i] <= 100)
            {
                f[j] += a[i];
                cout << a[i] << ' ' << j + 1 << endl;
                break;
            }
        if(j == idx)  // 增加一个箱子
        {
            f[idx ++ ] += a[i];
            cout << a[i] << ' ' << idx << endl;
        }
    }
    cout << idx;
    
    return 0;
}

5:CPA招新Ⅰ

作者 龙兴
单位 贵州工程应用技术学院

新学期开始啦,我们CPA是2019年6月成立的,创建时有20位元老。现在需要招新啦,每年新学期社团服务中心会组织百团大战。我们CPA迎来第一次招新,我们很期待迎来新成员。
每天都有元老去招新,每招到一个萌新,招新人会在纸上写一个大写字母。CPA共有竞赛部、宣传部、办公部、组织部四个部门。我们规定A代表竞赛部(Competition department),B代表宣传部(Propaganda Department)、C代表办公部(Office)、D组织部(Organization Department)。社团招新后需要统计每一个部门有多少人?

输入格式:
输入一行字符串,字符串长度不大于10000。

输出格式:
每输出一个部门换行。

输入样例:

AABBCCDD

输出样例:

Competition department 2 people!
Propaganda Department 2 people!
Office 2 people!
Organization Department 2 people!

备注:
也许有人调皮不止ABCD四个字符,真实人数以ABCD为准。
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

解析:根据题意模拟一遍过程

#include <iostream>
#include <algorithm>

using namespace std;

struct node
{
    string name;
    int num;
}f[4];

int main()
{
    string s;
    getline(cin, s);
    
    for (auto p : s)
        if(p >= 'A' && p <= 'D')
            f[p - 'A'].num ++;
    f[0].name = "Competition department";
    f[1].name = "Propaganda Department";
    f[2].name = "Office";
    f[3].name = "Organization Department";
    
    for (int i = 0; i < 4; i ++ )
        cout << f[i].name << ' ' << f[i].num << ' ' <<"people!\n";
    
    return 0;
}

6:CPA招新Ⅱ

作者 龙兴
单位 贵州工程应用技术学院

新学期开始啦,我们CPA是2019年6月成立的,创建时有20位元老。现在需要招新啦,每年新学期社团服务中心会组织百团大战。我们CPA迎来第一次招新,我们很期待迎来新成员。

每天都有元老去招新,每招到一个萌新,招新人会在纸上写一个大写字母。CPA共有竞赛部、宣传部、办公部、组织部四个部门。我们规定A代表竞赛部(Competition department),B代表宣传部(Propaganda Department)、C代表办公部(Office)、D组织部(Organization Department)。社团招新后需要统计每一个部门有多少人?有一天会长突然来了,需要你给他一份部门人员名单,名单需要根据人数从大到小排序的,聪明的你会直接写一个程序给会长,让他直接使用程序排序。

输入格式:
输入一行字符串,字符串长度不大于10000。

输出格式:
如果人数相同,按照字典序从小到大排序,每输出一个部门换行。

输入样例:

AABBCCCDDAA

输出样例:

Competition department 4 people!
Office 3 people!
Organization Department 2 people!
Propaganda Department 2 people!

备注
也许有人调皮不止ABCD四个字符,真实人数以ABCD为准。
代码长度限制
16 KB
时间限制
1000 ms
内存限制
64 MB

解析:根据题意模拟一遍过程

#include <bits/stdc++.h>

using namespace std;

const int N = 10010;

struct node{
    int num;
    string name;
}f[N];

bool cmp(node a, node b)
{
    if(a.num != b.num) return a.num > b.num;
    return a.name < b.name;
}
int cnt[4];

int main()
{
    string s;
    getline(cin, s);
    for (auto p : s)
        if(p >= 'A' && p <= 'D')
            cnt[p - 'A'] ++;
    for (int i = 0; i < 4; i ++ )
        f[i].num = cnt[i];
    f[0].name = "Competition department";
    f[1].name = "Propaganda Department";
    f[2].name = "Office";
    f[3].name = "Organization Department";
    
    sort(f, f + 4, cmp);
    
    for (int i = 0; i < 4; i ++ )
    {
        cout << f[i].name << " " << f[i].num << " ";
        cout << "people!\n";
    }
    return 0;
}

7:h0154.加勒比海盗船——最优装载问题

作者 黄正鹏
单位 贵州工程应用技术学院
6.png

在北美洲东南部,有一片神秘的海域,那里碧海 蓝天、阳光明媚,这正是传说中海盗最活跃的加勒比 海(Caribbean Sea)。17 世纪时,这里更是欧洲大陆 的商旅舰队到达美洲的必经之地,所以当时的海盗活 动非常猖獗,海盗不仅攻击过往商人,甚至攻击英国 皇家舰……
有一天,海盗们截获了一艘装满各种各样古董的 货船,每一件古董都价值连城,一旦打碎就失去了它 的价值。虽然海盗船足够大,但载重量为 C,每件古 董的重量为 wi,海盗们该如何把尽可能多数量的宝贝 装上海盗船呢?

输入格式:
第1行输入T组测试数据,每组测试数据输入载重量 c 及古董个数 n,下1行输入每个古董的重量wi,用空格分开.

输出格式:
每组能装入的古董最大数量

输入样例:

1
30 8
4 10 7 11 3 5 14 2

输出样例:

5

代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

解析:根据题意分析可知,我们只需要每次选择重量最小的古董就一定可以得到一组最优解,所以只需要排序从小到大遍历一遍即可

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 10010;

int m, n;
int w[N];

int main()
{
    int T;
    cin >> T;
    
    while (T -- )
    {
        cin >> m >> n;
        for (int i = 0; i < n; i ++ ) cin >> w[i];
        
        sort(w, w + n);
        
        int cnt = 0;
        for (int i = 0; i < n; i ++ )
        {
            if(w[i] <= m)
            {
                m -= w[i];
                cnt ++;
            }
        }
        cout << cnt << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值