一道简单dp

作者: 不知名小号 | 来源:发表于2018-10-15 20:11 被阅读6次

xwd丢给我的一道题,好像是他出的?

题面如下

(后面有中文解释)

A robot is located at the top-left corner of a m*n grid.
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid.
There is a positive integer in each small grid which means the score that the robot get when it passes this grid.
Now you need to calculate the top k total score when the robot reach the destination.
note: The top k total score may contain same total score got from different paths.
Example 1:
Input:
3 3
2
3 2 5
3 2 2
4 2 1
Output:
13 13
Example 2:
Input:
4 4
3
7 1 5 8
4 6 2 1
4 2 1 3
5 7 3 2
Output:
32 31 29
TEST 1: 1 <= n, m <= 4, k = 1
TEST 2-3: 1<= n, m, k<=4
TEST 4: 1<= n, m <= 100, k = 1
TEST 5-10: 1<=n, m, k<=100
For all, cost <= 100

题意:

简单说,有一个矩阵,矩阵的每个方格中放有若干金币,有一个机器人,他在矩阵的左上角,他要走到矩阵的右下角,他只能往下走或者往右走。要求他能得到的前k多的金币。输入规模如题面。

解:

本题简单版

应该有一道类似这样的dp,是求从左上角走到右下角,获得金币的最大值。这是比较好求的,因为对于所有i, j >= 2(下标从1开始)的第i行j列来说,它要么从上面i - 1行j列走过来,或者从左边i行 j - 1列走过来,对于每个点,选dp[i - 1][j]和dp[i][j - 1]中最大的,再加上本身的a[i][j]就是到达这个点时的最大值。还有边缘条件,对于第一行的每个点,除了第一行第一列以外,每个点因为只能从左边到达它,所以他们的dp值就是dp[1][i] = dp[1][i - 1] + a[1][i]。dp[1][1] = a[1][1]。每一列也如此。

进阶版

这道题让求的不是最大值,而是前k大值,那么可以考为每个点创建一个vector,也就是m*n个vector,设为vector<int> v[m][n]。对应上面的逻辑就是,对于每个i, j >= 2,v[i][j]等于v[i - 1][j]和 v[i][j - 1]对应的vector中的前k个,也就是两个数组组合到一起,然后前k个就是v[i][j]。边缘的条件也类似上面的,对于第一行来说,每个vector都只有一个元素,就是从第一行第一列元素走到第一行第i列元素时的元素和。

#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
#include <windows.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
#define maxn 107
const int inf = 0x3f3f3f3f;
int n, m, k;
// 返回两个vector中的前k大元素组成的vector
vector<int> findTopK(vector<int> a, vector<int> b, int t){
    vector<int> temp;
    vector<int> ans;
    for (int i = 0; i < (int)a.size(); i++){
        temp.push_back(a[i] + t);
    }
    for (int i = 0; i < (int)b.size(); i++){
        temp.push_back(b[i] + t);
    };
    sort(temp.begin(), temp.end());
    if ((int)temp.size() <= k){
        return temp;
    }
    else{
        for (int i = temp.size() - k; i < (int)temp.size(); i++){
            ans.push_back(temp[i]);
        }
        return ans;
    }
}
int main(int argc, char * argv[]) 
{
    while (cin >> n >> m >> k){
        int a[maxn][maxn];
        vector<int> v[maxn][maxn];
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= m; j++){
                cin >> a[i][j];
            }
        }
         // 处理边缘条件
        int temp = a[1][1];
        v[1][1].push_back(a[1][1]);
        for (int i = 2; i <= n; i++){
            temp += a[i][1];
            v[i][1].push_back(temp);
        }
        temp = a[1][1];
        for (int i = 2; i <= m; i++){
            temp += a[1][i];
            v[1][i].push_back(temp);
        }
        //dp
        for (int i = 2; i <= n; i++){
            for (int j = 2; j <= m; j++){
                v[i][j] = findTopK(v[i - 1][j], v[i][j - 1], a[i][j]);
            }
        }
  
        for (int i = 0; i < k; i++){
            int t = (int)v[n][m].size() - i - 1;
            cout << v[n][m][t] << " ";
        }
        cout << endl;
    }
    return 0;
}

相关文章

  • 一道简单dp

    xwd丢给我的一道题,好像是他出的? 题面如下 (后面有中文解释) A robot is located at t...

  • leetcode 64最小路径和

    很简单的题目 多打了一个等号 结果找错找了半天 也是使用了dp来完成这个题目这应该算是一道用来比较好理解dp的一道题目

  • 91-解码方法-细节决定成败

    写在前面 这是一道比较简单的DP问题,定义dp数组和寻找递推方程都很容易,不过多种情况实在是不太容易考虑周全,做题...

  • D - 4 HDU - 2845

    (简单dp???excuse??) dp:最大不连续子序列和

  • 3. Longest Substring Without Rep

    这是一道DP题,使用DP[i]来表示以I为结尾的子串的最大长度。转移关系式式DP[i+1]=Math.min(DP...

  • 8.24 - hard - 102

    552. Student Attendance Record II虽然知道这是一道DP题,但是这个dp状态真的很难...

  • coin change

    最简单的DP

  • 8.22 - hard - 86

    446. Arithmetic Slices II - Subsequence 一道dp的题目

  • LeetCode 300.最长上升子序列

    每天一道DP防止抑郁 每天一道BinarySearch防止自闭 很巧,这道题可以用这两种方法来解 动态规划做DP的...

  • [DP]62. Unique Paths

    62. Unique Paths 比较简单和基础的DP。Base:左边和上边,都是1.Transfer:dp[i]...

网友评论

    本文标题:一道简单dp

    本文链接:https://www.haomeiwen.com/subject/svrfzftx.html