当前位置: 首页 > news >正文

蓝桥杯 C++ b组李白打酒加强版,动规及dfs+记忆化搜索双解

题目大意:初始有2斗酒,遇到花会喝1斗,遇到店使当前酒翻倍,最后遇到的是花,且最好酒为0;并且不会出现酒<0的情况,给定经过了n次店,m次花,求总共有多少种遇到花和店的顺序、

解法1:动态规划
(1)状态数组:f[i][j][k]:已经经过了i个店和j个花,并且当前酒为k斗,其值表示为方案数
(2)状态转化公式:f[i][j][k]可以经过了一个店得到,也可以经过一个花得到
        a.店:到上一个店的方案数为f[i-1][j][k/2]:表示已经走了i-1个店,j个花,当前酒为k/2;
                   ps:i>=1,k%2==0

        b.花:到上一个花的方案数为f[i][j-1][k+1]:已经走了i个店,j-1个花,当前酒为k+1
                  ps:j>=1
(3)初始化:初始经过0个店和花,且酒为2,故应初始化f[0][0][2],并且不论经过一个花还是一个店,对于可能的下一项f[1][0][4]或者f[0][1][1],它俩的方案数肯定都是1,因为只能从f[0][0][2]得到,再结合我们的转化公式(详见代码吧,更好理解),可知初始化f[0][0][2]=1;

ps:下面的f[i][j][k],我们可以在使用前定义int& v=f[i][j][k],然后在本来使用f[i][j][k],替换为v了,可以去搜一下相关使用~~QWQ

参考代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 105,MOD=1e9+7;
using ll=long long;

int n,m;
int f[N][N][N];

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
    cin>>n>>m;
    f[0][0][2]=1;//经过0个花和店,手里2斗酒,即初始状态;
    for(int i=0;i<=n;i++)//店
    {
        for(int j=0;j<=m;j++)//花
        {
            for(int k=0;k<=m;k++)//不会超过花的次数
            {
                if(i>=1 && k%2==0) f[i][j][k]=(f[i][j][k]+f[i-1][j][k/2])%MOD;
                if(j>=1) f[i][j][k]=(f[i][j][k]+f[i][j-1][k+1])%MOD;
            }
        }
    }
    cout<<f[n][m-1][1];
    return 0;
}

解法2:dfs+记忆化搜索
(1)首先要考虑的是如何定义dfs,传的参数是什么?显然是店,花,酒,又因为咱们这里用正向搜索,这里就定义dfs(剩余的店,剩余的花,现在的酒)
(2)其次开一个三维数组,d[n][m][k]表示有n店,m花,此刻酒为k时到题中最后的情况(遇到花喝完酒)总共的方案数。一开始全部初始化为-1,即memset(d,-1,sizeof d);
(3)然后我们要明确dfs的返回值,这里先给公式
        d[n][m][k]=(dfs(n-1,m,k*2)+dfs(n,m-1,k-1))%MOD;
         余n店,m花的情况走一步只会得到余n-1店,m花余n店,m-1花的情况
         那么对于d[n][m][k]的值当然就是两种方案数相加,但k的变化需要注意一下,这里和动态规             划的k刚好相反,这里是由初始状态向后面走,所以时2*k和k-1。
(4)最后就到了记忆化了,首先已经搜过的可以不用重复搜,即d已经赋值了的,d!=-1时,直接返回当前d[][][];其次还可以特判一下非法的情况,比如,花和店以及酒到最后才是负数,不可能为0另外,酒的数量一定不会超过100,因为花的最大值为100,而每个花只能让酒-1最后如果花为0了,而此时店和酒还不为0,那么也不合法!因为店只会让酒增加,无论如何酒最后都不会为0;

最后就是代码了:
 

#include<bits/stdc++.h>
using namespace std;
const int N = 105,MOD=1e9+7;
using ll=long long;

int n,m;
int d[N][N][N];

int dfs(int n,int m,int k)//还余下n个店,m个花,现在酒为k
{
    if(n<0||m<0||k<0||k>=N||(!m&&(n||k))) return 0;
    if(~d[n][m][k]) return d[n][m][k];
    return d[n][m][k]=(dfs(n-1,m,k*2)+dfs(n,m-1,k-1))%MOD;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
    cin>>n>>m;
    memset(d,-1,sizeof d);
    d[0][1][1]=1;//最后的情况,剩下1个花,1斗酒
    cout<<dfs(n,m,2);
    return 0;
}

相关文章:

  • 机器学习框架
  • 31页PPT解析数据湖架构、数据湖和数据仓库的区别、湖仓一体化湖仓一体建设解决方案
  • 短视频下载去水印,用什么工具好?
  • 应用于稳态电池模块的 Fluent 等效电路模型
  • 双周报Vol.67: 模式匹配支持守卫、LLVM 后端发布、支持 Attribute 语法...多项核心技术更新!
  • 修复Electron项目Insecure Content-Security-Policy(网络安全策略CSP)警告的问题
  • AD21 PCB中无法选中元器件怎么办?
  • 《历史代码分析》5、动态控制列表的列
  • Java CAS(Compare-And-Swap)概念及原理
  • 程序代码篇---STM32串口通信
  • 18 | 实现简洁架构的 Handler 层
  • 【MySQL是怎么运行的】0、名词解释
  • NetworkManager服务与network服务的区别
  • 机器人路径规划、轨迹优化系列课程
  • Taro-Bluetooth-Print:让蓝牙打印也充满乐趣的开发组件库
  • STL —— 核心组成部分和特性概述
  • uniapp uview 1.0 跨域h5配置多个代理、如何请求接口
  • JavaWeb项目实际部署流程
  • CPS-J/S冲奖第15天:真题解析
  • Spring Boot集成Spring Statemachine
  • 工人日报:应对“职场肥胖”,健康与减重同受关注
  • 广西百色“致富果”:高品质芒果直供香港,带动近五千户增收
  • 征稿启事|澎湃·镜相第三届非虚构写作大赛暨2026第六届七猫现实题材征文大赛
  • 中拉互联网发展与合作论坛在西安开幕
  • 湖北宜化拟斥资超32亿加价回购“弃子”,布局上游煤炭业务
  • 新华时评:让医德医风建设为健康中国护航