洛谷P8612 取宝

经典的记忆化搜索,一开始因为最后的答案忘记加取模卡了半天,真是愚蠢至极。

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
using namespace std;

const int N = 55, mod = 1e9 + 7;

int f[N][N][15][15]; // 横坐标 纵坐标 最大值 数量
bool vis[N][N][15][15];
int n, m, k, a[N][N];

int dfs(int x, int y, int s, int top) // 当前在x,y  当前拿了s个, 当前的最大值是top
{
    int &res = f[x][y][s][top];
    if (vis[x][y][s][top])
        return res;
    vis[x][y][s][top] = 1;
    if (x == n && y == m)
    {
        if (s == k)
            f[x][y][s][top] = 1;
        return f[x][y][s][top];
    }
    if (x + 1 <= n)
    {
        res = (long long)(res + dfs(x + 1, y, s, top)) % mod;
        if (a[x + 1][y] > top)
            res = (long long)(res + dfs(x + 1, y, s + 1, a[x + 1][y])) % mod;
    }
    if (y + 1 <= m)
    {
        res = (long long)(res + dfs(x, y + 1, s, top)) % mod;
        if (a[x][y + 1] > top)
            res = (long long)(res + dfs(x, y + 1, s + 1, a[x][y + 1])) % mod;
    }
    return res;
}

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", &a[i][j]);
        }
    printf("%d\n", (dfs(1, 1, 0, -1) + dfs(1, 1, 1, a[1][1])) % mod);
    system("pause");
    return 0;
}

这里dfs的状态定义是从点(x,y)出发,且离开时携带的个数为s,上限为top

也可以定义成从(x,y)出发,且进入时的携带个数为……  

如果采用后者,就不需要在最后计算答案时两数相加了。

posted @ 2023-11-19 17:40  Gold_stein  阅读(9)  评论(0编辑  收藏  举报