京东笔试题目—寻宝藏dp解析

华电北风吹
天津大学认知计算与应用重点实验室
日期:2015/9/24

京东笔试题目,据说是蓝桥杯的原题。一道很容易想到用动态规划求解的题目。
矩阵寻宝,只能选择价值递增,有多少种正好选够k个的方案。
DP求解,自顶向下的dp解法
状态定义
dp[i][j][value][num]: 表示自顶向下求解到矩阵第i,j个元素的时候,已选最大价值为value,已选个数为num的方案数。
状态转移:
分为两步(注意不是两种情况):
1、在第i,j个方格不作选择
这时直接对能够转移到这个状态的状态的方案数相加即可。
2、选择第i,j个方格的宝物
对当前状态里面那些value<宝物价值的状态进行更新(加上选择当前宝物可以转移到此状态的种类数)
这里涉及到一个初始解问题,笔试的时候就是这里一直没想明白
当选择第i,j个方格的宝物的时候,dp[i][j][temp][1]增加了多少?
实际上这里增加的数目是从(1,1)到(i,j)的方格路径数。只要注意到上面这个状态初始解,这道题目就十分简单了。

#include <iostream>
#include <fstream>
using namespace std;

#define maxRow 15
#define maxCol 15
#define maxVal 15
#define maxNum 15

int value[maxRow][maxCol];
int dp[maxRow][maxCol][maxVal][maxNum];
int routeCount[maxRow][maxCol];

int RouteCountFunction(int m, int n)
{
    if (routeCount[m][n] > 0)
        return routeCount[m][n];
    if ((m == 1) || (n == 1))
    {
        routeCount[1][1] = 1;
        routeCount[m][n] = 1;
        return 1;
    }
    routeCount[m][n] = RouteCountFunction(m - 1,n) + RouteCountFunction(m,n - 1);
    return routeCount[m][n];
}

void DPfunc(int m, int n,int total)
{
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
        {
            for (int val = 0; val < maxVal; val++)
                for (int count = 0; count < maxNum; count++)
                    dp[i][j][val][count] = dp[i - 1][j][val][count] + dp[i][j - 1][val][count];
            int temp = value[i][j];
            dp[i][j][temp][1] += routeCount[i][j];
            for (int q = 2; q <= total; q++)
                for (int k = 0; k < temp; k++)
                    dp[i][j][temp][q] += dp[i - 1][j][k][q - 1] + dp[i][j - 1][k][q - 1];
        }
}
int main()
{
    ifstream in("input.txt");
    cin.rdbuf(in.rdbuf());
    int m, n, k;
    cin >> m >> n >> k;
    memset(dp, 0, sizeof(dp));
    memset(routeCount, 0, sizeof(routeCount));
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            cin >> value[i][j];
    RouteCountFunction(m, n);
    DPfunc(m, n, k);
    int result = 0;
    for (int i = 0; i<12; i++)
        result += dp[m][n][i][k];
    cout << result << endl;

    system("pause");
    return 0;
}

你可能感兴趣的:(京东笔试题目—寻宝藏dp解析)