蓝桥杯第三周算法竞赛D题&&E题

发现更多计算机知识,欢迎访问Cr不是铬的个人网站

D迷宫逃脱

拿到题目一眼应该就能看出是可以用动态规划来解决。但是怎么定义dp呢?

这个题增加难度的点就在当所在位置与下一个要去的位置互质的时候,会消耗一把钥匙。当没有钥匙的时候就不能移动了。想到这里,我们可以定义一个三维的dp数组.

  • 定义dp

dp[i][j][k]表示从位置(1,1)到(i,j)消耗k把钥匙的最大值

  • 初始化

memset(dp,-0x3f3f,sizeof(dp))

dp[i][j][0] = a[1][1]

  • 状态转移方程

dp[i][j][k] = max(dp[i][j][k],dp[i-1][j][k] + a[i][j])

dp[i][j][k] = max(dp[i][j][k],dp[i-1][j][k-1] + a[i][j])互质

dp[i][j][k] = max(dp[i][j][k],dp[i][j-1][k] + a[i][j])

dp[i][j][k] = max(dp[i][j][k],dp[i][j-1][k-1] + a[i][j])互质

  • 输出答案

从dp[n][m][0] ~ dp[n][m][k]找到最大的即可

AC代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
const LL maxn = 4e05+7;
const LL N=1e05+10;
const LL mod=1e09+7;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >t;
priority_queue<LL> q;
LL gcd(LL a, LL b){
    return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
    return a / gcd(a , b) * b;
}
int main()
{
    //不加不能AC
    //优化输入/输出操作的性能,并精确控制输出的格式
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    int n,m,p;
    //读入行宽与高还要钥匙数目
    cin>>n>>m>>p;
    //适当开大一点
    //dp[i][j][k]表示从(1,1)到(i,j)消耗k把钥匙的最大路径和
    LL dp[n+5][m+5][p+5];
    LL a[n+5][m+5];
    for(int i = 1; i <= n;i++)
        for(int j = 1; j <= m;j++)
            cin>>a[i][j];
    //初始化
    memset(dp,-0x3f3f,sizeof(dp));
    dp[1][1][0] = a[1][1];
    for(int i = 1;  i<= n; i++)
        for(int j = 1; j <= m;j++)
            for(int k = 0; k <= p; k++)
            {
                //能够从上转移
                if(i > 1)
                {
                    if(gcd(a[i-1][j],a[i][j]) == 1) {
                        if (k > 0)//不可能出现互质且没消耗一把钥匙的情况
                        { dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1] + a[i][j]); }
                    }
                    else { dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k] + a[i][j]); }
                }
                //能够从左边转移
                if(j > 1)
                {
                    if(gcd(a[i][j-1],a[i][j]) == 1) {
                        if (k > 0)//不可能出现互质且没消耗一把钥匙的情况
                        { dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k - 1] + a[i][j]); }
                    }
                    else { dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k] + a[i][j]); }
                }
            }
    //适当小一点
    LL maxx = -1e18;
    for(int i = 0; i <= p; i++)
        maxx = max(maxx,dp[n][m][i]);
    if(maxx>0)
        cout<<maxx<<endl;
    else
        cout<<-1<<endl;
    return 0;
}

E深秋的苹果

这个是一道二分的题目,中规中矩写就行,但是注意此题右端点要开很大!

AC代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
const LL maxn = 4e05+7;
const LL N=2e05+10;
const LL mod=1e09+7;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >t;
priority_queue<LL> q;
LL gcd(LL a, LL b){
    return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
    return a / gcd(a , b) * b;
}
int n,m;
int a[N];
bool check (LL mid)
{
    LL pre = 0, sum = 0,group = 1;//刚开始就是一组
    for(int i = 0;  i < n;i++)
    {
        if(pre + sum * a[i] <= mid)//可以分在一组
        {
            pre += sum*a[i];
            sum += a[i];
        }
        else//新开一组
        {
            group++;
            pre = 0;
            sum = a[i];//这组开始就是a[i]
        }
        if(group > m)return false;
    }
    return true;
}
int main() {

    //优化输入/输出操作的性能,并精确控制输出的格式
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    cin>>n>>m;
    for(int i = 0; i < n;i++)
        cin>>a[i];
    //二分思路
    LL l = 0, r = 3e18;//开大点,防止意外
    while( l < r)
    {
        LL mid = l + (r - l)/ 2; //避免可能的超界
        if(check(mid)) { r = mid; }
        else { l = mid + 1; }
    }
    cout<<l<<endl;

    return 0;
}

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
工业3D_大熊11 分钟前
3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
java·c++·3d·docker·c#·制造·数据可视化
暮色_年华25 分钟前
Modern Effective C++ Item 11:优先考虑使用deleted函数而非使用未定义的私有声明
c++
流星白龙28 分钟前
【C++习题】10.反转字符串中的单词 lll
开发语言·c++
Smile丶凉轩1 小时前
微服务即时通讯系统的实现(服务端)----(1)
c++·git·微服务·github
萝卜兽编程1 小时前
优先级队列
c++·算法
珹洺3 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
孙同学要努力3 小时前
C++知识整理day1——前置基础知识整理(命名空间、输入输出、函数重载、引用)
开发语言·c++
沐泽Mu3 小时前
嵌入式学习-C嘎嘎-Day05
开发语言·c++·学习
几窗花鸢3 小时前
力扣面试经典 150(下)
数据结构·c++·算法·leetcode
Beau_Will3 小时前
数据结构-树状数组专题(1)
数据结构·c++·算法