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


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

    D迷宫逃脱

    file 拿到题目一眼应该就能看出是可以用动态规划来解决。但是怎么定义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 
    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 pairpl;
    priority_queue, greater >t;
    priority_queue 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<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    E深秋的苹果

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

    AC代码:

    #include 
    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 pairpl;
    priority_queue, greater >t;
    priority_queue 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<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

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

  • 相关阅读:
    Shell 实现文件基本操作(切割、排序、去重)
    angular、 react、vue框架对比
    Web应用开发介绍
    公众号迁移操作流程是怎样的?
    【华为OD机试真题 JAVA】贪吃蛇
    Vue iconfont-阿里巴巴矢量图标库用法
    战略调整?顺丰科技将从深圳撤退到武汉!
    集群外Prometheus 集群 k8s
    Vue:object变化侦测
    .net core 读取 appsettings.json 值
  • 原文地址:https://blog.csdn.net/m0_73421035/article/details/134450115