• 2039: [蓝桥杯2022初赛] 李白打酒加强版 (动态规划)


     

    题目描述

    话说大诗人李白,一生好饮。幸好他从不开车。
    一天,他提着酒壶,从家里出来,酒壶中有酒 2 斗。他边走边唱:
    无事街上走,提壶去打酒。
    逢店加一倍,遇花喝一斗。
    这一路上,他一共遇到店 N 次,遇到花 M 次。
    已知最后一次遇到的是花,他正好把酒喝光了。
    请你计算李白这一路遇到店和花的顺序,有多少种不同的可能?
    注意:壶里没酒( 0 斗) 时遇店是合法的,加倍后还是没酒;但是没酒时遇花是不合法的。

    输入格式

    输入包含多组测试数据。
    第一行为T,表示存在T组测试数据,T不超过30。
    对于每组测试数据,输入两个整数N 和M.
    1 ≤ N, M ≤ 100。

    输出格式

    输出一个整数表示答案。由于答案可能很大,输出模1000000007 的结果。

    输入样例 复制

    1. 1
    2. 5 10

    输出样例 复制

    14

    最开始是没写出来的,想的是深度优先搜索,也就是第二个代码,不能AC,后面看别人的推荐,才知道闫学灿(y总)(acwing网站的创始人,开了很多课,我相信有必要去看一看,慢慢的把数据结构学了,也得准备CCF的CSP认证了),看了他讲的蓝桥杯初赛,才搞懂了,从侧面也能看出,我很弱,emm,确实,革命尚未成功,我得继续努力。

    分析:

    状态设计:dp[i][j][k]的值表示遇到i家店,j朵花,酒壶中还剩k斗酒的可能情况数;
        状态转移方程:dp[i][j][k]=dp[i-1][j][k/2](i>1&&k%2==0) + dp[i][j-1][k+1](j>1);
        边界设计:除了dp[0][0][2]=1,其他元素全为0;
        他一共遇到店 N 次,遇到花 M 次。已知最后一次遇到的是花, 他正好把酒喝光了;所以
        最后一次肯定遇到的是花,那么最后的结果便是dp[N][M-1][1];
        并且酒壶中酒的容量不能超过M;

    1. /**
    2. 再编码:
    3. 状态设计:dp[i][j][k]的值表示遇到i家店,j朵花,酒壶中还剩k斗酒的可能情况数;
    4. 状态转移方程:dp[i][j][k]=dp[i-1][j][k/2](i>1&&k%2==0) + dp[i][j-1][k+1](j>1);
    5. 边界设计:除了dp[0][0][2]=1,其他元素全为0;
    6. 他一共遇到店 N 次,遇到花 M 次。已知最后一次遇到的是花, 他正好把酒喝光了;所以
    7. 最后一次肯定遇到的是花,那么最后的结果便是dp[N][M-1][1];
    8. 并且酒壶中酒的容量不能超过M;
    9. */
    10. #include <cstdio>
    11. #include <cstring>
    12. using namespace std;
    13. const int mod=1000000007;
    14. int main()
    15. {
    16. int T;
    17. scanf("%d",&T);
    18. while(T--)
    19. {
    20. int n,m;
    21. scanf("%d%d",&n,&m);
    22. int dp[n+1][m+1][m+1];
    23. memset(**dp,0,sizeof(dp));
    24. dp[0][0][2]=1;
    25. for(int i=0;i<=n;++i)
    26. for(int j=0;j<=m;++j)
    27. for(int k=0;k<=m;++k)
    28. {
    29. int &val=dp[i][j][k];
    30. if(i>=1&&k%2==0)
    31. val=(val+dp[i-1][j][k/2])%mod;
    32. if(j>=1)
    33. val=(val+dp[i][j-1][k+1])%mod;
    34. }
    35. printf("%d\n",dp[n][m-1][1]);
    36. }
    37. return 0;
    38. }

     DFS解决
        只能AC 13%,不得不说,对于一个问题,不能找到正确的算法策略与正确的算法策略
        比较,可谓是天壤之别;

    1. /**
    2. DFS解决
    3. 只能AC 13%,不得不说,对于一个问题,不能找到正确的算法策略与正确的算法策略
    4. 比较,可谓是天壤之别;
    5. */
    6. #include <iostream>
    7. #include <cstdio>
    8. using namespace std;
    9. const int mod=1000000007;
    10. void drink_DFS(int store,int flow,int drink);
    11. int sum=0,N,M;
    12. int main()
    13. {
    14. int T;
    15. scanf("%d",&T);
    16. while(T--)
    17. {
    18. sum=0;
    19. scanf("%d%d",&N,&M);
    20. drink_DFS(0,0,2);
    21. printf("%d\n",sum);
    22. }
    23. return 0;
    24. }
    25. void drink_DFS(int store,int flow,int drink)
    26. {
    27. if(drink < 0) return;
    28. if(store > N || flow >= M) return;
    29. if(drink>M) return;
    30. if(store==N&&flow==M-1&&drink==1)
    31. {
    32. sum+=1;
    33. sum%=mod;
    34. return;
    35. }
    36. drink_DFS(store+1,flow,2*drink);
    37. drink_DFS(store,flow+1,drink-1);
    38. // store+=1;
    39. // drink*=2;
    40. // drink_DFS(store,flow,drink);
    41. // store-=1;
    42. // drink/=2;
    43. // flow+=1;
    44. // drink-=1;
    45. // drink_DFS(store,flow,drink);
    46. // flow-=1;
    47. // drink+=1;
    48. }

  • 相关阅读:
    第四章 将对象映射到 XML - 异常
    [C++]Leetcode17电话号码的字母组合
    一种基于最大似然的语音信号混响时间(reverberation time)估计方法的MATLAB实现
    齐博X1-栏目的终极方法get_sort
    Linux驱动开发:内核模块和字符设备驱动
    【Linux】GDB调试
    通过ORPO技术微调 llama3大模型(Fine-tune Llama 3 with ORPO)
    SQLyog 连接 MySQL8.0+ 报错2058
    公众号自定义菜单(含个性化)
    更新andriod studio版本,项目编译报could not find org.junit.jupiter:junit-jupiter
  • 原文地址:https://blog.csdn.net/qq_51825761/article/details/125622158