2024年暑假ACM集训第6场

A: 文件存储

题目描述

如果有n个文件{F1,F2,F3,…,Fn}需要存放在大小为M的U盘中,文件i的大小为Si,1<=i<=n。请设计一个算法来提供一个存储方案,使得U盘中存储的文件数量最多。

输入

多组输入,对于每组测试数据,每1行的第1个数字表示U盘的容量M(以MB为单位,不超过256*1000MB),第2个数字表示待存储的文件个数n。
第2行表示待存储的n个文件的大小(以MB为单位)。

输出

输出最多可以存放的文件个数。

样例输入 Copy
10000 5
2000 1000 5000 3000 4000
样例输出 Copy
4
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
int a[256005];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int m, n;
    while (cin >> m >> n)
    {
        for (int i = 0; i < n; i++)
            cin >> a[i];
        sort(a, a + n);
        int sum = 0;
        int t = 0;
        for (int i = 0; i < n; i++)
        {
            if (m - sum >= a[i])
            {
                sum += a[i];
                t++;
            }
            else
                break;
        }
        cout << t << "\n";
    }
    return 0;
}

 B: 汽车加油问题

题目描述

一辆汽车加满油后可以行驶n千米。旅途中有k个加油站。若要使沿途的加油次数最少,请设计一个有效的算法。

输入

第一行有2个正整数n和k,表示汽车加满油后可行驶nkm,且旅途中有k个加油站。接下来1行中,有k+1个整数,表示第k个加油站与第k-1个加油站之间的距离。第0个加油站表示出发地,汽车已加满油,且在第0个加油站满油不算加油,第k+1个加油站表示目的地。(请处理到文件尾)

输出

最少加油次数。如果无法到达目的地,则输出“No Solution”。

样例输入 Copy
7 7
1 2 3 4 5 1 6 6
样例输出 Copy
4
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
int a[10005];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, k;
    while (cin >> n >> k)
    {
        int s = n, sum = 0;
        for (int i = 0; i <= k; i++)
            cin >> a[i];
        for (int i = 0; i <= k; i++)
        {
            if (a[i] > n)
            {
                cout << "No Solution" << "\n";
                return 0;
            }
            if (s - a[i] >= 0)
                s -= a[i];
            else
            {
                sum++;
                s = n - a[i];
            }
        }
        cout << sum << "\n";
    }
    return 0;
}

 C: 遥望基地

题目描述

X星人迷失在Y星球,他必须尽快赶到在Y星球的基地,否则会耗尽所有能量而化成雕像。
现在X星人面前有N种能量药水,每一种药水都有一个体积和维持能量的距离(单位:光日,即光一天所走的距离),每次只能使用一种药水。当然一种药水用完后可以立即更换另一种药水。
X星人拥有一个体积为V的能量药水箱,可以通过药水箱携带若干种不同的能量药水。对于某一种能量药水,可以全部携带,也可以只携带一部分。
已知X星人当前距离基地M光日,请问X星人会变成雕像吗?当然,聪明的X星人每次都会尽量让自己走得最远。

输入

单组输入。
第1行输入三个正整数N、M和V,分别表示能量药水的数量、当前X星人与基地之间的距离(光日)和能量药水箱的体积,用空格隔开。($N,M,V<=10^4$)
接下来N行,每行两个正数(不一定是正整数),分别表示一种药水的体积和能够维持能量的距离(光日),两个正数之间用空格隔开。

输出

如果X星人会变成雕像则输出“Yes”,否则输出“No”。

样例输入 Copy
3 20 10
5 5
5 10
5 7.5
样例输出 Copy
No

 

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
struct S
{
    double v, s;
} a[10005];
bool cmp(S a, S b)
{
    return a.s > b.s;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m, V;
    cin >> n >> m >> V;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i].v >> a[i].s;
        a[i].s /= a[i].v;
    }
    sort(a, a + n, cmp);
    double sum = 0;
    for (int i = 0; i < n; i++)
        if (V > a[i].v)
        {
            V -= a[i].v;
            sum += a[i].v * a[i].s;
        }
        else
        {
            sum += V * a[i].s;
            break;
        }
    if (m > sum)
        cout << "No\n";
    else
        cout << "Yes\n";
    return 0;
}

 D: 最少代价

题目描述

X星人接到返回总部的紧急命令,他在驻地积蓄了满满的能量开始朝总部前进。为了能够在路上顺利获得能量补给,他带上了n枚X星币。
在驻地通往总部的路上有m个能量补给点,每补给一次X星人将损失一枚X星币。补给过后X星人又将能量满满,这些能量可以供X星人前行k千米。
X星人希望以最少的代价(损失的X星币最少)到达总部,请输出X星人最多可以剩多少枚X星币?
【注意:X星人出发时必然能量满满。】

输入

每组输入数据包含两行。
第1行包含三个用空格分隔开的正整数,分别对应n,m和k。(1 ≤ n ≤ 10000, 1 ≤ m ≤ 2000, 1 ≤ k ≤ 10000)
第2行包含m+1个正整数,两两之间用空格隔开。前面m个数字分别表示出发点到m个补给点的距离(距离小于10000),最后一个数字表示出发点到总部的距离。

输出

每组输出占1行,输出X星人最多还剩下的X星币数量。
如果X星人不能成功到达总部,则输出“No”。

样例输入 Copy
10 5 6
2 4 8 12 14 20
样例输出 Copy
7
#include <iostream>
#include <algorithm>
using namespace std;
int a[2005];
int main()
{
    int n, m, k;
    while (cin >> n >> m >> k)
    {
        for (int i = 1; i <= m + 1; i++)
            cin >> a[i];
        bool t = true;
        sort(a + 1, a + 2 + m);
        if (k < a[1])
            cout << "No" << '\n';
        else
        {
            int s = k;
            s -= a[1];
            for (int i = 2; i <= m + 1; i++)
            {
                if (s >= a[i] - a[i - 1])
                    s -= a[i] - a[i - 1];
                else
                {
                    s = k;
                    if (s < a[i] - a[i - 1])
                    {
                        t = false;
                        cout << "No" << '\n';
                        break;
                    }
                    s -= a[i] - a[i - 1];
                    n--;
                }
            }
            if (t)
                if (n > 0)
                    cout << n << '\n';
                else
                    cout << "No" << '\n';
        }
    }
    return 0;
}

 E: 最小积分

题目描述

Kimi和Sunny决定在线组队玩一个数字游戏,该游戏的规则如下:
(1) 游戏系统随机生成两组正整数,每组N个数字,两组正整数可能不一样;
(2) 每个游戏团队两个人,每个人拿其中一组数字;
(3) 每一轮两个人从自己的那组数字中各取出一个数字,将两个数字相乘作为这一轮的积分,取出的数字不能再重复使用;
(4) 一共玩N轮,将每轮的积分求和,得到一个总积分;
(5) 总积分最小的队伍获胜。
现在需要你编写一个程序帮Kimi和Sunny计算出最小积分和。

输入

单组输入。
第1行输入一个正整数N,N不超过100。
第2行输入N个不超过1000的正整数,表示Kimi拿到的数字,两两之间用空格隔开。
第3行输入N个不超过1000的正整数,表示Sunny拿到的数字,两两之间用空格隔开。

输出

输出最小积分和。

样例输入 Copy
3
3 1 2
4 3 5
样例输出 Copy
22
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
int a[105], b[105];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    for (int i = 0; i < n; i++)
        cin >> b[i];
    sort(a, a + n);
    sort(b, b + n, greater<int>());
    int sum = 0;
    for (int i = 0; i < n; i++)
        sum += a[i] * b[i];
    cout << sum << "\n";
    return 0;
}

 F: HNUCM的批改作文

题目描述

HNUCM的小王老师给同学们布置了一道小作文题,要求所有同学同时提交并现场批改。
批改完的同学即可以下课,否则就需要等待老师把自己的作文批改完才能够下课。
交小作文的时间到了,N个同学同时把作文提交给了小王老师,小王老师根据大家写的字数估算了一下批改时间(单位:分钟),现在请你编写一个程序帮助小王老师做一个决策,使得所有同学等待作文批改的平均时间最少,请输出最少平均等待时间(单位:分钟)。

输入

单组输入。
第1行输入一个不超过100的正整数N。
第2行输入N个不超过20的正整数,每一个正整数对应一个同学的作文批改时间(单位:分钟),两个正整数之间用英文空格分隔。

输出

输出所有同学的作文都批改完时的最少平均等待时间(单位:分钟),结果四舍五入保留两位小数。

样例输入 Copy
3
10 5 20
样例输出 Copy
18.33
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int a[100];
int main()
{
 
    int n;
    cin>>n;
    double f=0,s=0;
        for(int i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    for(int i=0;i<n;i++)
        {
            s+=a[i];
            f+=s;}
    printf("%.2lf",f/n);
}

 G: X星人的礼物

题目描述

六一儿童节到了,X星人宝宝收到了很多很多礼物。他决定把这些礼物装到自己的礼物箱中。为此,他准备了很多个型号相同的礼物箱,每个礼物箱能够装礼物的最大重量都是一样的。但是X星人宝宝不希望在一个礼物箱里面装太多礼物(可能担心礼物会被压坏吧),每个礼物箱最多只允许装2个礼物
假设X星人宝宝收到了N个礼物,现在给出每一个礼物的重量和一个礼物箱的最大装载量,请你编写一个程序计算X星人宝宝最少要用多少个礼物箱才能够把所有的礼物都装完

输入

单组输入。
每组两行,第1行输入两个正整数,分别表示礼物的数量N和每个礼物箱的最大装载量C,其中1<=N<=1000,1<=C<=100,两者之间用英文空格隔开。
第2行输入N个不超过100的正整数,分别表示每一个礼物的重量,两两之间用英文空格隔开。
输入保证最重的礼物的重量<=C。

输出

针对所输出的数据,输出将所有的礼物全部都装完所需的礼物箱的最少个数。

样例输入 Copy
5 80
20 70 40 30 10
样例输出 Copy
3

 

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
int a[1005];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    sort(a, a + n);
    int l = 0, r = n - 1;
    int s = 0;
    while (l <= r)
    {
        if (a[l] + a[r] <= m)
        {
            l++;
            r--;
        }
        else
        {
            r--;
        }
        s++;
    }
    cout << s << "\n";
    return 0;
}

 H: 小h的规划

题目描述

小h是一个很有规划的人,他列了很多事情,标注了优先级(1-9)也标注了必要程度(1-5)必要程度大的排前面,必要程度一样优先级大的排前面,必要程度一样,优先级一样不改变初始顺序。因为事情太多了,所以小h需要你帮忙..

输入

第一行一个数字n表示有n个事情
后n行每行两个数字a,b表示事情的优先级和必要程度
(n<=10000)

输出

将所有事情排序输出(只输出初始序号)

样例输入 Copy
2
9 3
1 4
样例输出 Copy
2 1

 

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
struct S
{
    int id;
    int x;
    int y;
} a[10005];
bool cmp(S x, S y)
{
    if (x.y != y.y)
        return x.y > y.y;
    if (x.x != y.x)
        return x.x > y.x;
    return x.id < y.id;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i].x >> a[i].y;
        a[i].id = i;
    }
    sort(a + 1, a + n + 1, cmp);
    for (int i = 1; i <= n; i++)
        cout << a[i].id << " ";
    cout << "\n";
    return 0;
}

 I: 李华上大学了吗?(III)

题目描述

李华顺利地到达了巴黎,他的笔友Peter带他开启了他的巴黎之旅。
途中,李华遇到了许多心动的纪念品想要带回家,但是他又不想自己太累,而且他买纪念品也有相应的预算k,现给出他心动的纪念品清单:共有n件,其中每件都各有其价格price,重量weight,心动值v(其中心动值为1~5之间的数值),需要注意的是:在心动值不同的情况下,李华会优先选择心动值大的纪念品;若心动值相同,李华会优先选择比较便宜的纪念品,具体见样例。同时给出李华在保证不累的情况下,最多能拿的物品重量m。在不超过预算并且保证不累的情况下,李华最多可以带几件纪念品回家?

输入

第一行三个整数,分别为:纪念品件数n,最多能拿的物品重量m,预算k。(n<1e5,m<100,k<10000,k的单位为元,m的重量为kg)
第二行到第n+1行,分别为每件物品的价格price,重量weight,心动值v。(price<10000,weight<100,v为1~5之间的整数,price的单位为元,weight的重量为kg)

输出

在不超过预算并且保证不累的情况下,李华最多可以带回家的纪念品件数。

样例输入 Copy
3 10 1000
100 5 3
50 3 2
300 3 3
样例输出 Copy
2
提示

由于李华会优先选择心动值大的物品,所以李华选择了第一件和第三件物品。

 

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
struct S
{
    int pri, wei, v;
} a[100005];
bool cmp(S a, S b)
{
    if (a.v == b.v)
    {
        if (a.pri == b.pri)
            return a.wei < b.wei;
        return a.pri < b.pri;
    }
    return a.v > b.v;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < n; i++)
        cin >> a[i].pri >> a[i].wei >> a[i].v;
    sort(a, a + n, cmp);
    int s = 0, w = 0, p = 0;
    for (int i = 0; i < n; i++)
        if (w + a[i].wei <= m && p + a[i].pri <= k)
        {
            w += a[i].wei;
            p += a[i].pri;
            s++;
        }
    cout << s << "\n";
    return 0;
}

 J: 消灭病毒

题目描述

小明最近喜欢上了一款“消灭病毒”的游戏。游戏中有各种各样不同的病毒,消灭的病毒越多,得分越高。但是在游戏中,玩家一旦被病毒击中将减少一定的生命值。
在游戏中,玩家可以通过添加不同的药水来获取生命值。生命值越高,在游戏中存活的时间越长。
游戏一共提供了N种药水,第i种药水的体积为V(i),补充的生命值为L(i)。
玩家可以携带一个体积为V的药水瓶。每一种药水可以全部装入药水瓶,也可以只装入一部分。当然,如果你装入一部分药水,那么也只能补充这一部分药水按比例对应的生命值。
请问如何装入药水可以使得初始的生命值最大?请输出最大的初始生命值。

输入

单组输入。
第1行输入两个正整数V和N,分别表示药水瓶的体积和药水的种类数。(N<=100)
接下来N行,每行包含两个正整数,分别对应第i种药水的体积V(i)和生命值L(i)。

输出

输出最大的初始生命值(四舍五入保留两位小数)。

样例输入 Copy
10 3
5 6
3 3
4 2
样例输出 Copy
10.00

 

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
struct S
{
    double x, y;
} a[105];
bool cmp(S a, S b)
{
    return a.y > b.y;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    double v;
    cin >> v >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i].x >> a[i].y;
        a[i].y /= a[i].x;
    }
    sort(a, a + n, cmp);
    double s = 0;
    for (int i = 0; i < n; i++)
        if (v >= a[i].x)
        {
            v -= a[i].x;
            s += a[i].x * a[i].y;
        }
        else
        {
            s += v * a[i].y;
            break;
        }
    printf("%.2lf\n", s);
    return 0;
}

 K: 破解密码

题目描述

X星人最近截取了Y星人的一段数字密文,这是一段长度为N(N>=2)的十进制正整数数字密文,且第1位是非零数。
聪明的X星人通过仔细分析和研究,终于找到了破解方法。破解过程非常复杂,包含若干步骤,其中第一步如下:
这段数字密文的第1位是一个密钥,设该密钥为K(K<N)。从这段数字密文中去掉K个数字后将得到一个新的正整数,其中所得到的最大正整数即为可用于进一步处理的中间码。
你能否编写一段程序帮助X星人将数字密文转换为对应的中间码?

输入

单组输入。
每组一行,输入一个长度为N的十进制正整数。(2<=N<=1000)

输出

输出数字密文所对应的中间码。

样例输入 Copy
246135
样例输出 Copy
6135

 

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    string a;
    cin >> a;
    int k = a[0] - '0';
    int n = a.size();
    string s = "";
    for (int i = 0; i < n; i++)
    {
        if (n - i <= k)
            break;
        int x = -1, y = -1;
        for (int j = i; j <= k + i; j++)
            if (a[j] - '0' > x)
            {
                x = a[j] - '0';
                y = j;
            }
        s += to_string(x);
        k -= y - i;
        i = y;
    }
    cout << s << "\n";
    return 0;
}

 L: 奥运日

题目描述

由于受到新冠肺炎疫情的影响,2020东京奥运会在推迟一年后终于举行啦!即便是在暑假,“爱学习”的小米同学每周也只能有一天时间看奥运会的比赛。
今天的比赛异常精彩,很多项目都来到了最后的决赛。小米是个有强迫症的小伙子,如果他决定看一个比赛项目,就希望能够从头到尾完整地看完。
已知有2个电视频道在全天转播奥运电视节目,现给出这2个电视频道的节目转播时间表,请问小米最多可以看多少个完整的比赛项目(每个比赛项目对应一个电视节目)?
注:为了对问题进行简化,节目转播时间表只包含比赛项目的开始时间和结束时间(开始时间计入比赛时间,结束时间不计入比赛时间),且不考虑2个电视频道之间的切换时间,2个电视频道转播的比赛项目也不存在重复。

输入

单组输入。
第1行输入两个正整数M和N,分别表示两个电视频道转播的比赛项目(电视节目)的个数,二者之间用空格隔开,每个电视频道每一天的总节目数不超过30个。
接下来输入2行,每1行表示1个电视频道的节目转播时间表,每一个电视节目的开始时间和结束时间用24小时制表示,包含小时和分钟,格式为:HH:MM-HH:MM,例如:11:30-13:40。每两个比赛项目时间之间用空格隔开。

输出

输出这一天小米最多可以观看的完整比赛项目的个数。

样例输入 Copy
3 4
08:00-09:00 09:30-11:00 13:00-15:00
07:00-08:00 08:00-11:00 12:00-13:30 14:00-17:00
样例输出 Copy
5
提示

小米可以观看第1个频道的第1个、第2个节目,第2个频道的第1个、第3个和第4个项目,总共可以观看5个完整的比赛项目。

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cmath>
#include <unordered_map>
#include <sstream>
using namespace std;
int m, n, s;
struct S
{
    int l, r;
} a[100];
bool cmp(S x, S y)
{
    return x.r < y.r;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> m >> n;
    for (int i = 1; i <= m; i++)
    {
        int h1, m1, h2, m2;
        char c, d, e;
        cin >> h1 >> c >> m1 >> d >> h2 >> d >> m2;
        a[i].l = h1 * 60 + m1;
        a[i].r = h2 * 60 + m2;
    }
    for (int i = 1; i <= n; i++)
    {
        int h1, m1, h2, m2;
        char c, d, e;
        cin >> h1 >> c >> m1 >> d >> h2 >> d >> m2;
        a[m + i].l = h1 * 60 + m1;
        a[m + i].r = h2 * 60 + m2;
    }
    sort(a + 1, a + 1 + m + n, cmp);
    int sum = 0;
    for (int i = 1; i <= m + n; i++)
        if (a[i].l >= sum)
        {
            s++;
            sum = a[i].r;
        }
    cout << s << endl;
    return 0;
}

 M: X星切糕

题目描述

据说在X星上有一种切糕,这种切糕呈细长形状,并且按长度来进行售卖。
更有意思的是,不同长度的切糕其价格不一样。定价规则如下:
1单位长度:价值为3枚X星币。
2单位长度:价值为7枚X星币。
3单位长度:价值为11枚X星币。
4单位长度:价值为15枚X星币。
5单位长度:价值为20枚X星币。
现有一块N个单位长度的切糕,需要将其切成若干小段,每一小段的长度均不超过5个单位长度,请问可以得到的最大价值是多少枚X星币?

输入

单组输入。
输入一个正整数N表示切糕的总长度,N<=10^6。

输出

输出切成小段之后可以得到的最大价值(X星币的枚数)。

样例输入 Copy
12
样例输出 Copy
47
#include<stdio.h>
int main()
{
    int n,s;
    scanf("%d",&n);
    s=20*(n/5);
    n%=5;
    if(n==4)
        s+=15;
    else if(n==3)
        s+=11;
    else if(n==2)
        s+=7;
    else if(n==1)
        s+=3;
    printf("%d\n",s);
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值