首页 > 学院 > 开发设计 > 正文

蓝桥杯第五届 地宫取宝 (四维线性dp)

2019-11-10 20:13:50
字体:
来源:转载
供稿:网友
  问题描述  X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。  地宫的入口在左上角,出口在右下角。  小明被带到地宫的入口,国王要求他只能向右或向下行走。  走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。  当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。  请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。输入格式  输入一行3个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)  接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值输出格式  要求输出一个整数,表示正好取k个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。样例输入2 2 21 22 1样例输出2样例输入2 3 21 2 32 1 5样例输出14题目分析:数据量不大,考虑用四维dp,dp[i][j][ma][num]表示到点(i,j)时最大值为ma取得了num个宝贝的方法数,对于某个点如果它的宝藏值大于当前最大值,则我们可以取也可以不取,否则我们只能不取,因此转移方程:if(ma < val[i][j])  dp[i] [j] [ val[i][j] ] [num + 1] = (dp[i] [j] [ val[i][j] ] [num + 1] + dp[i - 1] [j] [ma] [num] + dp[i] [j - 1] [ma] [num]) % MOD //取dp[i] [j] [ma] [num] = (dp[i] [j] [ma] [num] +dp[i - 1] [j] [ma] [num] + dp[i] [j - 1] [ma] [num]) % MOD //不取 (这里没有else,因为不论我们能不能取,我们都可以选择不取),最后我们只要累加dp[n][m][各最大值][k]的值即可,初始dp[1][1][val[1][1]][1] = 1第一个点取,dp[1][1][0][0]第一点不取这题还有两个坑点,第一:上述转移方程要分成两段写,因为是对1e9+7取模,我们考虑最坏的情况,括号里的数就可能超int。第二:宝物的价值有可能是0,因为初始化为0,因此混淆了空的点和价值为0的点,因此我们让每个宝藏的价值自增1
#include <cstdio>#include <cstring>#define MOD 1000000007int dp[55][55][15][15];int val[55][55];int main(){    int n, m, k;    scanf("%d %d %d", &n, &m, &k);    for(int i = 1; i <= n; i++)    {        for(int j = 1; j <= m; j++)        {            scanf("%d", &val[i][j]);            val[i][j] ++;        }    }    memset(dp, 0, sizeof(dp));    dp[1][1][val[1][1]][1] = 1;    dp[1][1][0][0] = 1;    for(int i = 1; i <= n; i++)    {        for(int j = 1; j <= m; j++)        {            if(i == 1 && j == 1)                continue;            for(int num = 0; num <= k; num++)            {                for(int ma = 0; ma <= 13; ma++)                {                    if(ma < val[i][j])                    {                        dp[i][j][val[i][j]][num + 1] = (dp[i][j][val[i][j]][num + 1] + dp[i - 1][j][ma][num]) % MOD;                        dp[i][j][val[i][j]][num + 1] = (dp[i][j][val[i][j]][num + 1] + dp[i][j - 1][ma][num]) % MOD;                        }                    dp[i][j][ma][num] = (dp[i][j][ma][num] + dp[i - 1][j][ma][num]) % MOD;                    dp[i][j][ma][num] = (dp[i][j][ma][num] + dp[i][j - 1][ma][num]) % MOD;                }            }        }    }    int ans = 0;    for(int i = 0; i < 13; i++)        ans = (ans + dp[n][m][i][k]) % MOD;    PRintf("%d/n", ans);}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表