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

题目:

蓝桥杯真题——地宫取宝(动态规划)_第1张图片

蓝桥杯真题——地宫取宝(动态规划)_第2张图片

分析:

由题目容易知道使用动态规划来解决,设定一个四维数组 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 
#include 
#include 
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;
}

你可能感兴趣的:(#,动态规划)