动态规划-1620. 收集硬币

2020-04-08 07:45:18

问题描述:

给定一个n * m个的矩阵,矩阵的每个位置有一定数量的硬币,你从(0,0)位置出发,每次只能往右或者往下走,当他经过某个格子的时候,可以得到这个格子上的所有硬币,当它走到第(n-1,M-1)位置时游戏结束,在游戏开始前,你有?次机会,可以交换某两个格子中的硬币数量中,k次机会不一定要使用完,求从(0,0)走到第(n-1,M-1)所能得到的最大的硬币数量。

样例

输入:
matrix = [[9,9,9,0,0],[0,0,9,0,0],[0,0,0,0,0],[0,0,9,0,0],[9,0,9,9,9]]
k = 1
输出:81

注意事项

  • 2≤n,m≤50
  • 0<=k<=20
  • 0<=matrix[I][j]<=1000000

问题求解:

    int nums[55];
    int dp[55][55][25][25];
    int collectingCoins(vector<vector<int>> &matrix, int k) {
        // Write your code here
        int n = matrix.size();
        int m = matrix[0].size();
        memset(dp, -0x3f,sizeof(dp));
        dp[0][0][0][0] = matrix[0][0], dp[0][0][0][1] = 0;
        for(int x = 0; x < n; x++) {
            for(int y = 0; y < m; y++) {
                if (x == 0 && y == 0) continue;
                int idx = 0;
                if(x) {
                    for(int j = y + 1; j < m; j++) {
                        nums[idx++] = matrix[x - 1][j];
                    }
                }
                for(int j = 0; j < y; j++) {
                    nums[idx++] = matrix[x][j];
                }
                sort(nums,nums + idx,greater<int>());
                for(int used = 0; used <= k;used ++)
                {
                    for(int blank = 0;blank <= x + y + 1 && blank <= k; blank++)
                    {
                        int res = INT_MIN;
                        if(x) {
                            res = max(res, dp[x - 1][y][used][blank] + matrix[x][y]);
                            if(blank)
                            {
                                res = max(res,dp[x - 1][y][used][blank - 1]);
                            }
                            int sum = 0;
                            int it = 0;
                            for(int cntuse = 1;cntuse <= used && cntuse <= idx;cntuse ++)
                            {
                                sum += nums[it++];
                                res = max(res,dp[x - 1][y][used - cntuse][blank] + matrix[x][y] + sum);
                                if(blank)
                                {
                                    res = max(res,dp[x - 1][y][used - cntuse][blank - 1] + sum);
                                }
                            }
                        }
                        if(y)
                        {
                            res = max(res,dp[x][y - 1][used][blank] + matrix[x][y]);
                            if(blank)
                            {
                                res = max(res,dp[x][y - 1][used][blank - 1]);
                            }
                        }
                        dp[x][y][used][blank] = res;
                    }
                }
            }
        }
        int res = 0;
        for(int i = 0;i <= k; i++) {
            res = max(res,dp[n - 1][m - 1][i][i]);
        }
        return res;
    }

  

原文地址:https://www.cnblogs.com/hyserendipity/p/12657660.html

时间: 2024-10-16 02:39:28

动态规划-1620. 收集硬币的相关文章

动态规划之收集苹果

路径经过的最大值(最小值):原题:平面上有N*M个格子,每个格子中放着一定数量的苹果.从左上角的格子开始, 每一步只能向下走或是向右走,每次走到一个格子就把格子里的苹果收集起来, 这样一直走到右下角,问最多能收集到多少个苹果. 不妨用一个表格来表示: {5, 8, 5, 7, 1, 8},    {1, 3, 2, 8, 7, 9},    {7, 8, 6, 6, 8, 7},    {9, 9, 8, 1, 6, 3},    {2, 4,10, 2, 6, 2},    {5, 5, 2,

百练_4120 硬币(DP)

描述 宇航员Bob有一天来到火星上,他有收集硬币的习惯.于是他将火星上所有面值的硬币都收集起来了,一共有n种,每种只有一个:面值分别为a1,a2… an. Bob在机场看到了一个特别喜欢的礼物,想买来送给朋友Alice,这个礼物的价格是X元.Bob很想知道为了买这个礼物他的哪些硬币是必须被使用的,即Bob必须放弃收集好的哪些硬币种类.飞机场不提供找零,只接受恰好X元. 输入 第一行包含两个正整数n和x.(1 <= n <= 200, 1 <= x <= 10000)第二行从小到大为

NOI 4976:硬币

描述 宇航员Bob有一天来到火星上,他有收集硬币的习惯.于是他将火星上所有面值的硬币都收集起来了,一共有n种,每种只有一个:面值分别为a1,a2- an. Bob在机场看到了一个特别喜欢的礼物,想买来送给朋友Alice,这个礼物的价格是X元.Bob很想知道为了买这个礼物他的哪些硬币是必须被使用的,即Bob必须放弃收集好的哪些硬币种类.飞机场不提供找零,只接受恰好X元. 输入 第一行包含两个正整数n和x.(1 <= n <= 200, 1 <= x <= 10000)第二行从小到大为

五大常用算法 之 动态规划法

一.基本概念 动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 动态规划是运筹学中用于求解决策过程中的最优化数学方法.当然,我们在这里关注的是作为一种算法设计技术,作为一种使用多阶段决策过程最优的通用方法.它是应用数学中用于解决某类最优化问题的重要工具. 如果问题是由交叠的子问题所构成,我们就可以用动态规划技术来解决它,一般来说,这样的子问题出现在对给定问题求解的递推关系中,这个递推关

codecombat之Sarven沙漠1-12关代码分享

codecombat中国游戏网址:http://www.codecombat.cn/ 所有代码为javascript代码分享 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1.沙丘 // 收集硬币,忽略砂耗牛和树榴.和投掷者,食人魔战斗. loop { enemy = this.findNearestEnemy(); item = this.findNearestItem(); flag = this.findFlag(); if (flag) { this.pick

Codecombat 游戏攻略——JavaScript编辑语言——关卡(计算机科学三)Ⅱ

第21关:有用的对手 // 这片满是硬币的地方暗藏了致命的毒药. // 食人魔正在进攻,而差役尝试偷你的硬币! while (true) { var enemy = hero.findNearestEnemy(); if (enemy) { // 只在敌人类型不是 "peon" 的时候攻击. if (enemy.type != "peon") { hero.attack(enemy); } } var item = hero.findNearestItem(); i

「网易官方」极客战记(codecombat)攻略-森林-插旗子Drop the Flag

简介 在使用 pickUpFlag() 之前,使用 buildXY() 在 flag 的位置建造一个 "fire-trap" . coin(金币)就像 flag 那样,也有 pos 属性.使用 coin 的 pos 加上 moveXY() 收集它们. 使用你的pickUpFlag方法去选择你放置的标志 - 但首先,使用buildXY来建立一个标志所在的fire-trap. 就像在上一关卡一样,每个硬币项目都是一个对象,每个标志也是一个对象.每个标志和项目对象都有一个post属性,代表它

「网易官方」极客战记(codecombat)攻略-森林-致命追随

简介 使用你的pickUpFlag方法去选择你放置的标志 - 但首先,使用buildXY来建立一个标志所在的fire-trap. 只是继续收集硬币,直到你看到一些食人魔来临,然后回去并在X上制造一个陷阱来阻止它们. 不要在每个X上建立陷阱,否则你将没有时间收集所有的硬币. 你必须击败食人魔,所以栅栏行不通. 您必须迅速作出反应,及时放置标志以阻止它们! 如果你在代码中遇到了麻烦,检查一下你做了什么.请记住,每个标志和项目对象都有一个pos属性,它具有'x和y属性,您可以使用'moveXY和bui

【算法设计与分析基础】20、动态规划-硬币搜集问题

题目: 在n*m格木板中放有一些硬币,每格的硬币数目最多为一个.在木板左上方的一个机器人需要搜集尽可能多的硬币并把他们带到右下方的单元格,每一步,机器人可以从当前的位置向右移动一格 或者向下移动一格,当机器人遇到一个有硬币的单元格的时,就会将这枚硬币搜集起来 解题: 硬币收集的时候,我们 从结果状态开始看,当搜集当前硬币的时候,只有两种方式,从上往下搜集,或者从左向右搜集 也就是当前f[i,j] = max{f[i, j - 1], f[i - 1, j]},初始化第一行和第一列,从第二行和列开