2024年春季学期《算法分析与设计》练习11

问题 A: 最少硬币

[命题人 : admin]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 847提交量: 1342统计

题目描述

假设有4种硬币,它们的面值分别为1分、5分、10分和25分。
现在要找给顾客n分钱。
请问怎样找零钱才能使给顾客的硬币个数最少?
输出所需最少硬币的枚数。

输入

输入需要找给顾客的零钱n(单位:分)。

输出

输出所需最少硬币的枚数。

样例输入 Copy
8
10
63
样例输出 Copy
4
1
6
while True:
    n=int(input())
    print(n//25+(n%25)//10+(n%25%10)//5+n%5)

问题 B: X星纸币

[命题人 : admin]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 364提交量: 1207统计

题目描述

X星最新版纸币的面额很奇怪,一共有1元、4元、9元、16元、25元、100元六种不同的面额。
已知每种面额纸币的数量不限,现在需要从中选取若干张纸币组成N元(N为正整数)。
请编写一个程序计算组成N元最少需要的纸币数量。

输入

单组输入。
每组1行,包含一个正整数N,N<=10^6。

输出

输出组成N元最少需要的纸币数量。

样例输入 Copy
12
样例输出 Copy
3
提示

组成12元最少需要3张面值都是4的纸币。

n = int(input())
exp = [1, 4, 9, 16, 25, 100]
dp = [float('inf')] * (n + 1)
dp[0] = 0
for i in range(1, n + 1):
    for j in exp:
        if i - j >= 0:
            dp[i] = min(dp[i], dp[i - j] + 1)
print(dp[n])

时间复杂度只能是O(n) 

问题 C: 图书排序

[命题人 : 201501010119]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 1070提交量: 2254统计

题目描述

某图书销售管理系统需要对图书(Book)进行排序,每一本图书包含书名(bookName)、销量(bookSales)、价格(bookPrice)等属性,要求先按照销量由大到小排序,对于销量相同的图书再按照价格由小到大排序。

输入

每组输入包括两个部分,第一部分为书的数量n,
接下来n行则为n本书的信息。 按顺序输入书名(不超过20个字)、销量、价格。

输出

输出排序后的信息,每个属性用空格隔开

样例输入 Copy
7
C++程序设计 120 25.00
软件工程 96 48.00
高等数学 80 32.50
算法分析与设计 96 54.00
离散数学 96 28.00
计算机网络 96 36.00
操作系统 115 45.00
样例输出 Copy
C++程序设计 120 25.00
操作系统 115 45.00
离散数学 96 28.00
计算机网络 96 36.00
软件工程 96 48.00
算法分析与设计 96 54.00
高等数学 80 32.50
n = int(input())
exp = []
for _ in range(n):
    name, sale, p = input().split()
    exp.append({
        'name': name,
        'sale': int(sale),
        'p': float(p)
    })
exp.sort(key=lambda x: (-x['sale'], x['p']))
for i in exp:
    print(f"{i['name']} {i['sale']} {i['p']:.2f}")

问题 D: 月饼

[命题人 : admin]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 1005提交量: 4070统计

题目描述

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

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

输入

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

输出

对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。(四舍五入)

样例输入 Copy
3 20
18 15 10
75 72 45
样例输出 Copy
94.50

c++ 

#define _CRT_SECURE_NO_WARNINGS 1 
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
struct cake {
    double num = 0;
    double sale = 0;
    double pns = 0;
} moon[1010];
bool cmp(cake a, cake b) {
    return (a.pns - b.pns) > 0;
}
int main() {
    int n = 0;
    double s = 0;
    double total = 0;
    scanf("%d%lf", &n, &s);
    for (int i = 1; i <= n; i++) {
        scanf("%lf", &moon[i].num);
    }
    for (int i = 1; i <= n; i++) {
        scanf("%lf", &moon[i].sale);
        moon[i].pns = moon[i].sale / moon[i].num;
    }
    sort(moon + 1, moon + n + 1, cmp);
 
    for (int j = 1; j <= n; j++) {
        if (s < moon[j].num) {
            total += s * moon[j].pns;
            break;
        }
        else if (s >= moon[j].num) {
            total += moon[j].sale;
            s -= moon[j].num;
        }
    }
    printf("%.2f", total);
    return 0;
}

python代码 

def solve(a, b, lst1, lst2):
    lst3 = []
    for i in range(a):
        lst3.append(lst2[i] / lst1[i])
    s = 0
    price = 0.0
    while s < b:

        if sum(lst1) < b:
            price = sum(lst2)
            break
        j = lst3.index(max(lst3))
        if s + lst1[j] < b:
            s += lst1[j]
            price += lst2[j]
            lst3[j] = 0
        elif s + lst1[j] == b:
            price += lst2[j]
            break
        else:
            price += (b - s) * lst3[j]
            break
    return price


while True:
    a, b = map(int, input().split())
    lst1 = list(map(float, input().split()))
    lst2 = list(map(float, input().split()))

    print('{:.2f}'.format(solve(a, b, lst1, lst2)))

问题 E: 汽车加油问题

[命题人 : 201501010119]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 1094提交量: 5143统计

题目描述

一辆汽车加满油后可以行驶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
while True:
    n, k = map(int, input().split())
    a = list(map(int, input().split()))
    p = 0
    s = 0
    if max(a) > n:
        print("No Solution")
    else:
        for i in range(k + 1):
            if s + a[i] <= n:
                s += a[i]
            else:
                p += 1
                s = a[i]
        print(p)

问题 F: 最大收益

[命题人 : admin]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 35提交量: 45统计

题目描述

小X是一位精明的投资人,他每次都能够做出正确的投资判断。现在有N个项目,每个项目的总投资额和总收益已知,并且每一个项目都允许小X投资一部分,当然也就只能拿到一部分收益。
现在小X决定拿出M万元钱来进行投资,请你帮他设计一个算法来计算最大收益和。

输入

对于每一个样例,第1行包含两个正整数,分别是M和N,其中M<=10^6,N<=100。
第2行一共有2*N个整数(不一定是正整数),奇数位置(即2*N-1位置)的数字表示第N个项目的总投资额(万元),偶数位置(即2*N位置)的数字表示第N个项目的总收益(万元),两个数字之间用空格隔开。

输出

小X可以获得的最大收益和(万元,结果保留两位小数)。

样例输入 Copy
100 4
50 10 20 10 40 10 50 20
样例输出 Copy
37.50
n, m = map(int, input().split())
a = list(map(int, input().split()))
b = []
c = []
d = []
p = []
for i in range(2 * m):
    if i % 2 == 0:
        b.append(a[i])
    else:
        c.append(a[i])
for i in range(m):
    d.append(c[i] / b[i])
k = 0
for i in range(m):
    k = 0
    for j in range(m):
        if d[i] > d[j]:
            k += 1
    p.append(k)
s = 0.0
q = 0
for j in range(m):
    for i in range(m):
        if p[i] == max(p) - q:
            q += 1
            if n <= b[i]:
                s += c[i] * n / b[i]
                n = 0
            else:
                n -= b[i]
                s += c[i]
print("%.2f" % s)

问题 G: 组个最小数

[命题人 : admin]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 163提交量: 256统计

题目描述
给定数字0-9各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意0不能做首位)。例如:
给定两个0,两个1,三个5,一个8,我们得到的最小的数就是10015558。
现给定数字,请编写程序输出能够组成的最小的数。
输入
每个输入包含1个测试用例。每个测试用例在一行中给出10个非负整数,顺序表示我们拥有数字0、数字1、……数字9的个数。整数间用一个空格分隔。
10个数字的总个数不超过200,且至少拥有1个非0的数字。
输出
在一行中输出能够组成的最小的数。
样例输入 Copy
2 2 0 0 0 3 0 0 1 0
样例输出 Copy
10015558
exp = list(map(int, input().split()))
flag = 0
ans = ''
for i in range(1, 10):
    if exp[i] != 0:
        flag = i
        exp[i] -= 1
        break
for i in range(10):
    for j in range(exp[i]):
        ans += str(i)
print(str(flag) + ans)

问题 H: 最后一滴血

[命题人 : 外部导入]

时间限制 : 1.000 sec  内存限制 : 128 MB

提交问题列表

解决: 42提交量: 67统计

题目描述

在ACM/ICPC这样的程序设计竞赛中,最早解出一道题称为抢到FB(First Blood,第一滴血)。现在ACM/ICPC世界总决赛甚至为每道题的FB设立了特别奖。
也许我们还可以设一个LB(Last Blood,最后一滴血)奖,奖给最后一个解出某题的队伍。注意:你不能先提交程序,得到Yes之后等比赛快结束时把它再交一遍,因为一旦一只队伍解出了某题,它对该题的所有后续提交都会被忽略。所有有本事的话,应该是写完程序以后先不交,等到比赛快结束时才交。当然,这样做浪费了很多罚时并且还有WA的风险,所以LB奖才显得有趣。
输入一场比赛中所有提交和对应的结果,输出每道题的LB奖得主。

输入

输入仅包含一组数据。第一行为题数n、队伍数t和提交数m(5<=n<=12, 10<=t<=100, 1<=m<=1000)。以下m行每行包含time(0~300之间的整数,单位:分钟), teamID(1~t), problem(A~L)和结果(Yes或者No)。提交按照时间从小到大排序,所以即使两个提交的time相同,也有先后顺序(可能只差几秒钟)。任意两个提交的顺序都不会绝对相同,因此LB奖要么空缺,要么有惟一的得主。

输出

对于每组数据,输出每道题目的LB奖得主的提交时间和teamID,格式见样例。

样例输入 Copy
5 10 18
0 2 B No
11 2 B Yes
20 3 A Yes
35 8 E No
40 8 E No
45 7 E No
50 10 A Yes
100 4 A No
120 6 B Yes
160 2 E Yes
180 2 A Yes
210 3 B Yes
240 10 B No
250 10 B Yes
270 2 B Yes
295 8 E Yes
295 7 E Yes
299 10 D Yes
样例输出 Copy
A 180 2
B 250 10
C - -
D 299 10
E 295 7

c++代码: 

#define _CRT_SECURE_NO_WARNINGS 1
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1017;
struct pro
{
    int a, b, c;
}RE[maxn];
int main()
{
    int n, t, m;
    int ti[maxn], ID[maxn], pp[maxn], re[maxn];
    char t1, t2[7];
    int f[117][117];
scanf("%d%d%d", &n, &t, &m);
        int i;
        memset(ti, 0, sizeof(ti));
        memset(ID, 0, sizeof(ID));
        memset(pp, 0, sizeof(pp));
        memset(re, 0, sizeof(re));
        memset(f, 0, sizeof(f));
        for (i = 0; i < n; i++)
        {
            RE[i].b = 0;
            RE[i].c = 0;
        }
        for (i = 0; i < m; i++)
        {
            scanf("%d%d", &ti[i], &ID[i]);
            getchar();
            scanf("%c%*c%s", &t1, t2);
            pp[i] = t1 - 'A' + 1;
            if (strcmp(t2, "Yes") == 0)
                re[i] = 1;
            else
                re[i] = 0;
 
        }
        int h = 0;
        for (i = 0; i < m; i++)
        {
            if (re[i] == 1)
            {
                if (f[ID[i]][pp[i]] == 0)
                {
                    h = pp[i];
                    RE[h].b = ID[i];
                    RE[h].c = ti[i];
                    f[ID[i]][pp[i]] = 1;
                }
            }
        }
        for (i = 0; i < n; i++)
        {
            printf("%c ", i + 'A');
            if (RE[i + 1].b != 0)
                printf("%d %d\n", RE[i + 1].c, RE[i + 1].b);
            else
            {
                printf("- -\n");
            }
        }
    return 0;
}

python代码:

while True:
    n, t, m = map(int, input().split())
    arr = []
    pno = []
    for i in range(m):
        time, tid, p, res = map(str, input().split())
        arr.append([int(time), int(tid), p, res])
    exp = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L']
    for i in range(n):
        pno.append(exp[i])
    res = []
    for i in range(len(pno)):
        ans = ' - -'
        solvetid = []
        solvetime = []
        for j in range(m):
            if arr[j][2] == pno[i] and arr[j][3] == 'Yes':
                solvetid.append(arr[j][1])
                solvetime.append(arr[j][0])
        solvetid = solvetid[::-1]
        solvetime = solvetime[::-1]
        for j in range(len(solvetid)):
            if solvetid[j] not in solvetid[j + 1:]:
                ans = ' ' + str(solvetime[j]) + ' ' + str(solvetid[j])
                break
        res.append(pno[i] + ans)
    for i in range(len(res)):
        print(res[i])

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值