蓝桥杯真题——地宫取宝(动态规划)

题目:

在这里插入图片描述

在这里插入图片描述

分析:

由题目容易知道使用动态规划来解决,设定一个四维数组 dp[55][55][15][15],此数组用于存放当前的行动方案数量,由题目给出的数据范围可以推测出设定的数组不会使内存爆炸,dp[i][j][k][c]我们定义为到 (i,j) 这个点时,拿到了k件物品,并且当前的物品的最大价值小于c的方案数,那么可以推测出下面几种情况:

  • 当mat[i][j] > 目前的最大价值(mat[i][j]表示位于(i,j)坐标的物品的价值)时,也就是说此时如果要取走(i,j)坐标的物品,那么位于(i-1,j)和(i,j-1)坐标的价值肯定小于mat[i][j],那么此时设置一个tmp1
    tmp1 = dp[i-1][j][k-1][mat[i][j]] + dp[i][j-1][k-1][mat[i][j]]

  • 不管mat[i][j]大于当前的最大价值时,也可以选择不取位于(i,j)的物品,当mat[i][j]小于当前的最大价值时,则不能取走(i,j)的物品,所以不管是大于还是小于,都存在不取的这种情况,此时设置一个tmp2
    tmp2 = dp[i-1][j][k][c] + dp[i][j-1][k][c]

最后 dp[i][j][k][c] = (tmp1%mod + tmp2%mod)%mod即可得出当前的方案数
最后输出dp[n][m][k][13]

代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int MOD = 1e9+7;
int mat[55][55];
int dp[55][55][15][15];
int n,m,k,ans;

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            scanf("%d",&mat[i][j]);
    int tmp1,tmp2;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            for(int l=0;l<=k;++l)
                for(int c=0;c<=13;++c)
                {
                    tmp1 = 0;
                    if(i==1&&j==1)   //此处表示初始条件
                    {
                        if(l==0) dp[i][j][l][c] = 1;
                        if(l==1&&c>mat[i][j]) dp[i][j][l][c]=1;
                        continue;
                    }
                    if(c>mat[i][j]&&l) tmp1 = dp[i-1][j][l-1][mat[i][j]] + dp[i][j-1][l-1][mat[i][j]];
                    tmp2 = dp[i-1][j][l][c] + dp[i][j-1][l][c];
                    dp[i][j][l][c] = (tmp1%MOD+tmp2%MOD)%MOD;
                }
    printf("%d\n",dp[n][m][k][13]);
    return 0;
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值