2024-科大XF-三语言题解

💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历

👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸

✨ 笔试合集传送们 -> 🧷学长刷题笔记

🍒 本专栏已收集 140+ 套题 🍄 题面描述等均已改编,如果和你实际看到的题面描述不一样请理解,做法和题目本质基本不变。

🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力 💞

alt

💌 01.硬币最少组合问题

问题描述

K小姐有一个爱好就是收集各种硬币。有一天,她在整理自己的硬币收藏时,突然想到了一个有趣的问题。如果给定一个总金额 ,能够用手上现有的硬币面值组合成该金额,需要的硬币数量最少是多少枚呢?

现在已知K小姐有 种不同面值的硬币,分别为 元,每种面值的硬币数量都是无限的。请你帮助K小姐设计一个程序,快速计算出给定总金额所需的最少硬币组合。

输入格式

输入仅包含一个正整数 ,表示要求组合的目标总金额,单位为元。

输出格式

输出最少硬币组合,从大到小按面值顺序输出,硬币面值间用空格分隔。若无法用现有面值组合出目标总金额,则输出

样例输入

8

样例输出

5 2 1

数据范围

题解

这是一个典型的动态规划问题。可以定义一个一维数组 ,其中 表示组合成金额 所需的最少硬币数量。

先将 数组初始化为一个较大的值,表示暂时无法组合出该金额。然后对于每一种面值的硬币,遍历 ,尝试更新 的值。具体来说,对于面值为 的硬币,可以将金额 拆分为 两部分,即 ,表示组合成金额 的最少硬币数等于组合成金额 的最少硬币数再加上当前这枚面值为 的硬币。

最后,再从 开始回溯,找出凑成总金额的硬币组合方案。具体做法是,从 开始,如果 ,即找到了上一个状态,就将两个状态的差值 加入答案数组中,然后令 ,直到 减小到 为止。因为要求输出的硬币面值要从大到小排列,所以最后再对答案数组逆序输出即可。

参考代码

  • Python
import sys

n = int(sys.stdin.readline().strip())
coins = [1, 2, 5, 10, 20, 50, 100]
INF = float('inf')

dp = [INF] * (n + 1)
dp[0] = 0

for val in coins:
    for j in range(val, n + 1):
        dp[j] = min(dp[j], dp[j - val] + 1)

if dp[n] == INF or n == 0:
    print(-1)
    exit(0)

result = []
last, j = n, n
while j >= 0:
    if dp[j] == dp[last] - 1:
        result.append(last - j)
        last = j
    j -= 1

print(*reversed(result))
  • Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] coins = {1, 2, 5, 10, 20, 50, 100};
        int INF = Integer.MAX_VALUE;
        
        int[] dp = new int[n + 1];
        Arrays.fill(dp, INF);
        dp[0] = 0;
        
        for (int val : coins) {
            for (int j = val; j <= n; j++) {
                dp[j] = Math.min(dp[j], dp[j - val] + 1);
            }
        }
        
        if (dp[n] == INF || n == 0) {
            System.out.println(-1);
            return;
        }
        
        List<Integer> result = new ArrayList<>();
        int last = n, j = n;
        while (j >= 0) {
            if (dp[j] == dp[last] - 1) {
                result.add(last - j);
                last = j;
            }
            j--;
        }
        
        Collections.reverse(result);
        for (int num : result) {
            System.out.print(num + " ");
        }
    }
}
  • Cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int INF = 0x3f3f3f3f;

int main() {
    int n;
    cin >> n;
    vector<int> coins = {1, 2, 5, 10, 20, 50, 100};
    
    vector<int> dp(n + 1, INF);
    dp[0] = 0;
    
    for (int val : coins) {
        for (int j = val; j <= n; j++) {
            dp[j] = min(dp[j], dp[j - val] + 1);
        }
    }
    
    if (dp[n] == INF || n == 0) {
        cout << -1 << endl;
        return 0;
    }
    
    vector<int> result;
    int last = n, j = n;
    while (j >= 0) {
        if (dp[j] == dp[last] - 1) {
            result.push_back(last - j);
            last = j;
        }
        j--;
    }
    
    reverse(result.begin(), result.end());
    for (int num : result) {
        cout << num << " ";
    }
    
    return 0;
}

🗳 02.单词拆分问题

问题描述

LYA最近在学习一门新的外语,他发现有些外来词在词典中并没有收录。为了方便学习和记忆,他想将这些生词拆分成词典中已有的单词。

现在给定一个词典,其中每个单词都有一个正整数权重。对于一个待拆分的单词,可以将其拆分成词典中出现的单词,且拆分得到的单词序列的权重之和最大。

例如,词典中有 三个单词,权重分别为 。对于单词 ,可以拆分成 ,对应的权重之和分别为 ,因此应该拆分为

假设词典中最多有 个单词,每个单词的长度不超过 个字符。请你帮助LYA设计一个程序,能够根据词典将输入的单词拆分成权重之和最大的形式。

输入格式

第一行包含整数 ,表示词典中单词的个数。

接下来 行,每行包含一个单词和对应的权重值,以空格分隔。

最后一行输入一个待拆分的单词。

输出格式

如果可以将输入的单词拆分,则输出拆分后的结果,单词之间用 隔开。如果无法拆分,则原样输出待拆分的单词。

样例输入

7
ba 1
cef 2
cefs 3
s 2
dok 6
sdok 9
ok 3
bacefsdok

样例输出

/ba/cef/sdok

数据范围

单词长度

题解

本题可以使用动态规划来解决。设 表示将前 个字符拆分得到的最大权重和, 表示前 个字符拆分得到最大权重和时,最后一个单词的前一个字符的下标。

我们可以从前往后枚举每个字符作为当前拆分的结束位置,然后枚举上一个单词的结束位置,判断中间这一段是否能在词典中找到。如果能找到,就更新

最后,如果 的值没有被更新过,说明无法拆分,原样输出单词。否则,从 开始,依次向前跳转,就能得到拆分的单词序列。

参考代码

  • Python
def main():
    n = int(input())
    words = {}
    for _ in range(n):
        word, weight = input().split()
        words[word] = int(weight)

    s = input()
    m = len(s)
    dp = [-float('inf')] * (m + 1)
    fore = [-1] * (m + 1)
    dp[0] = 0

    for i in range(1, m + 1):
        for j in range(i):
            word = s[j:i]
          

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

本专栏短期内不再更新,请勿继续订阅

全部评论

相关推荐

点赞 评论 收藏
分享
评论
2
3
分享

创作者周榜

更多
牛客网
牛客企业服务