DP\记忆化搜索-牛客寒假集训营3-牛牛的DRB迷宫I

22 篇文章 0 订阅

DP-牛客寒假集训营3-牛牛的DRB迷宫I

题目:
在这里插入图片描述
题意:

求 迷 宫 问 题 的 方 案 数 量 。 与 — — 求迷宫问题的方案数量。与—— DP题型总结 中 的 《 摘 花 生 》 类 似 。 中的《摘花生》类似。

暴 搜 三 个 分 支 指 数 级 别 的 复 杂 度 必 然 会 T 暴搜三个分支指数级别的复杂度必然会T T

一 、 记 忆 化 搜 索 : 一、记忆化搜索:

每 个 点 只 递 归 一 次 用 数 组 d p 来 保 存 , 当 再 次 搜 索 这 个 点 的 时 候 可 以 直 接 返 回 值 无 序 递 归 。 每个点只递归一次用数组dp来保存,当再次搜索这个点的时候可以直接返回值无序递归。 dp

#include<bits/stdc++.h>
using namespace std;
const int MAXN=55;
const long long mod=1e9+7;
int n,m;
char s[MAXN][MAXN];
long long dp[MAXN][MAXN];
long long dp_dfs(int x,int y)
{
    if(x>n||y>m)return 0;
    if(dp[x][y]!=-1)return dp[x][y];
    if(s[x][y]=='D')return dp[x][y]=dp_dfs(x+1,y);
    if(s[x][y]=='R')return dp[x][y]=dp_dfs(x,y+1);
    if(s[x][y]=='B')return dp[x][y]=(dp_dfs(x+1,y)+dp_dfs(x,y+1))%mod;
}
int main()
{
    scanf("%d %d",&n,&m);
    memset(dp,-1,sizeof(dp));
    dp[n][m]=1;
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s[i]+1);
    }
    printf("%lld\n",dp_dfs(1,1));
    return 0;
}

二 、 递 推 写 法 : 二、递推写法:

按 照 递 归 写 法 写 D P : d p [ i ] [ j ] 从 ( i , j ) 位 置 走 到 ( n , m ) 位 置 的 方 案 数 。 则 d p [ n ] [ m ] = 1 。 按照递归写法写DP:dp[i][j]从(i,j)位置走到(n,m)位置的方案数。则dp[n][m]=1。 DPdp[i][j](i,j)(n,m)dp[n][m]=1

① 、 m p [ i ] [ j ] = R : d p [ i ] [ j ] = d p [ i ] [ j + 1 ] ①、mp[i][j]=R:dp[i][j]=dp[i][j+1] mp[i][j]=R:dp[i][j]=dp[i][j+1]
② 、 m p [ i ] [ j ] = D : d p [ i ] [ j ] = d p [ i + 1 ] [ j ] ②、mp[i][j]=D:dp[i][j]=dp[i+1][j] mp[i][j]=D:dp[i][j]=dp[i+1][j]
③ 、 m p [ i ] [ j ] = R : d p [ i ] [ j ] = d p [ i + 1 ] [ j ] + d p [ i ] [ j + 1 ] ③、mp[i][j]=R:dp[i][j]=dp[i+1][j]+dp[i][j+1] mp[i][j]=R:dp[i][j]=dp[i+1][j]+dp[i][j+1]

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1e9+7;
const int maxn=55;
int n,m;
char mp[maxn][maxn];
ll dp[maxn][maxn];

int dfs(int x,int y)//暴搜
{
    if(x<1||y<1||x>m||y>n) return 0;
    if(x==n&&y==m) return 1;
    if(mp[x][y]=='R') return dfs(x,y+1)%mod;
    if(mp[x][y]=='D') return dfs(x+1,y)%mod;
    if(mp[x][y]=='B') return (dfs(x+1,y)+dfs(x,y+1))%mod;
}

int main()
{
    memset(mp,'!',sizeof(mp));

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>mp[i][j];

    dp[n][m]=1;
    int i,j;
    for(i=n;i>=1;i--)
        for(j=m;j>=1;j--)
        {
            if(i==n&&j==m) continue;
            if(mp[i][j]=='R') dp[i][j]=dp[i][j+1]%mod;
            if(mp[i][j]=='D') dp[i][j]=dp[i+1][j]%mod;
            if(mp[i][j]=='B') dp[i][j]=(dp[i+1][j]+dp[i][j+1])%mod;
        }
    cout<<dp[1][1]%mod<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值