第十二届蓝桥杯B组省赛部分真题

文章介绍了两道编程题的解决方案,第一题通过优化暴力求解,利用约数找货物摆放方式;第二题使用DFS和动态规划(DP)求解砝码称重问题,展示了从深度优先搜索到状态转移矩阵的优化过程。

试题D:货物摆放

看到题目首先想到用暴力的方法去求解,三个for循环去求解,但是n位一个16位数值,直接暴力肯定会时间超限的,于是我们得想方法优化它,不能想到可以只写两个for循环,全排列出前两个数,第三个数通过n=L*W*H的公式变换为H=n/W/H去确定第三个未知数。但是,还是超限。继续思考优化的点,暴力还是不太可行,可以发现,因为n=L*W*H,故L和W和H都为n的约数,这样只要我们把n的约数求出来(一共才百来个),再在这些约数中暴力求解即可。
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;

// 求约数
vector<long long> get_divisors(long long n)
{
    vector<long long> divisors;
    // 减少循环次数
    long long t = sqrt(n);
    for (long long i = 1; i <= t; i++)
    {
        // 能整除说明为一个约数,则有一个与之对应的约数 n/i
        if (n % i == 0)
        {
            divisors.push_back(i);
            if (i != n / i)
                divisors.push_back(n / i);
        }
    }
    return divisors;
}
int main()
{
    long long n, ans = 0;
    cin >> n;

    vector<long long> vec = get_divisors(n);
    for (int i = 0; i < vec.size(); i++)
        for (int j = 0; j < vec.size(); j++)
            if (n % (vec[i] * vec[j]) == 0)
                ans++;
    cout << ans << endl;

    system("pause");
    return 0;
}

试题G:砝码称重

考点

DP动态规划、DFS(骗分)

题解

解法1 DFS(50%)

#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <set>

using namespace std;

int n, w[110], flag[110];
set<int> ans;
void dfs(int sum1, int sum2)
{
    // 两种对称情况,剪枝即可
    if (sum1 < sum2)
        return;
    // 根据set结构的特性插入可能的结果
    else if (sum1 > sum2)
        ans.insert(sum1 - sum2);
    for (int i = 1; i <= n; i++)
    {
        if(!flag[i])
        {
            // 标记已经被选择过了
            flag[i] = 1;
            // 进行dfs深搜,将砝码选中放到左边
            dfs(sum1 + w[i], sum2);
            // 将砝码选中放到右边
            dfs(sum1, sum2 + w[i]);
            // 回溯标记
            flag[i] = 0;
        }
    }
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> w[i];
    dfs(0, 0);
    cout << ans.size();

    system("pause");
    return 0;
}

解法2 dp

一般来说能够深搜的题且是求方案数的都可以用DP来优化,这题就是最好的例证。(引用别人的图)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <set>

using namespace std;

// 一维为第几个砝码,二维为重量
bool dp[110][200010];
int main()
{
    int n, w[110] = {}, ans = 0, sum = 0;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> w[i];
        sum += w[i];
    }
    // 初始化
    dp[0][0] = true;
    for (int i = 1; i <= n; i ++)
        for(int j = 0; j <= sum; j++)
        // 考虑第 i 个的情况,分别为不选中该砝码,放入左边天平和放入右边
            dp[i][j] = dp[i-1][j] || dp[i-1][j+w[i]] || dp[i-1][abs(j-w[i])];
    for (int i = 1; i<=sum; i++)
        if (dp[n][i])
            ans ++ ;
    cout << ans;
    system("pause");
    return 0;
}

### 关于第十二届蓝桥杯Java B 对于希望了解或参与第十二届蓝桥杯Java B的情况,虽然具体题目和官方解析文档未直接提及[^1],可以基于以往事的特点来推测该届比的内容结构。 #### 比概述 蓝桥杯全国软件和信息技术专业人才大是一项面向大学生的编程竞活动。每年的比都会设置不同难度级别的题目供参者挑战。针对Java B而言,通常涉及算法设计、数据结构应用以及程序逻辑优化等方面的知识点测试。 #### 题目类型预测 根据往年的模式,预计第十二届蓝桥杯Java B也会包含如下几类典型问题: - **基础算法题**:考察基本的数据处理能力和常见算法的应用能力。 - **动态规划与递推关系构建**:这类题目往往需要选手能够识别并建立有效的状态转移方程来进行求解。 - **图论模型构建**:涉及到网络流、最短路径等问题背景下的解决方案寻找。 - **字符串操作技巧**:包括但不限于正则表达式的运用、高效匹配方法的选择等。 为了更好地准备此类竞,建议深入学习上述知识点,并通过练习历年真题加深理解。此外,还可以关注官方发布的最新通知获取更多关于特定年度比的具体信息。 ```java // 示例代码片段用于说明如何解决某类经典问题之一——最大子数和问题 public class MaxSubArray { public static int maxSubArray(int[] nums) { if (nums == null || nums.length == 0) return 0; int currentSum = nums[0]; int maxSum = nums[0]; for (int i = 1; i < nums.length; ++i){ currentSum = Math.max(nums[i], currentSum + nums[i]); maxSum = Math.max(maxSum, currentSum); } return maxSum; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值