一、Problem

Given three integers n, m and k. Consider the following algorithm to find the maximum element of an array of positive integers:

You should build the array arr which has the following properties:

  • arr has exactly n integers.
  • 1 <= arr[i] <= m where (0 <= i < n).
  • After applying the mentioned algorithm to arr, the value search_cost is equal to k.

Return the number of ways to build the array arr under the mentioned conditions. As the answer may grow large, the answer must be computed modulo 10^9 + 7.

Input: n = 2, m = 3, k = 1
Output: 6
Explanation: The possible arrays are [1, 1], [2, 1], [2, 2], [3, 1], [3, 2] [3, 3]

二、Solution

方法一:暴搜(超时)

  • 结束条件

    • 当前选择个数等于 n 并且剩余搜索代价为 0,返回 1
    • 当前选择个数不等于 n 但剩余搜索代价为小于 0,返回 0
  • 本层递归的责任
    • 找到最大值,结合最大值讨论搜索代价。
  • 剪枝:如果剩余可选数如果比剩余搜索代价还要小,一定不存在剩余搜索代价 cost=0cost = 0cost=0 的情况了。
class Solution {int mod = (int) 1e9 + 7, n, m, k;int dfs(int idx, int cur, int cost) {if (n - idx < cost)return 0;if (idx == n && cost == 0)return 1;if (cost < 0)return 0;int t = 0;for (int i = 1; i <= m; i++) {if (cur < i)  t += dfs(idx+1, i, cost-1);else         t += dfs(idx+1, cur, cost);}return t % mod;}public int numOfArrays(int n, int m, int k) {this.n = n; this.m = m; this.k = k;return dfs(0, -1, k);}
}

复杂度分析

  • 时间复杂度:O(2m)O(2^m)O(2m),
  • 空间复杂度:O(n)O(n)O(n),

方法二:记忆化

  • 定义状态

    • f[i][j][k]f[i][j][k]f[i][j][k] 表示第 iii 个数选 jjj 且搜索代价剩余 kkk 时的方案数,这里应该改为:表示前 iii 个数最大数位 jjj 且搜索代价剩余 kkk 时的方案数。
  • 思考初始化:
    • f[0...n][1...m][0...k]=−1f[0...n][1...m][0...k] = -1f[0...n][1...m][0...k]=−1
  • 思考状态转移方程
    • 如果 p>jp > jp>j,则有 f[i][j][k]+=dfs(i+1,p,k−1)f[i][j][k] += dfs(i+1, p, k-1)f[i][j][k]+=dfs(i+1,p,k−1)
    • 如果 p⩽jp \leqslant jp⩽j,则有 f[i][j][k]+=dfs(i+1,j,k)f[i][j][k] += dfs(i+1, j, k)f[i][j][k]+=dfs(i+1,j,k)
  • 思考输出:f[0][0][k]f[0][0][k]f[0][0][k] 因为状态计算是自底向上的,最后返回到初始状态,这和 dp 稍有不同

小心溢出…

class Solution {int mod = (int) 1e9+7, n, m;long f[][][];long dfs(int i, int j, int k) {if (n - i < k)        //剩下的数的个数比l小,无论如何也用不完k,所以返回0return 0;if (i == n && k == 0)return 1;if (k < 0)return 0;if (f[i][j][k] != -1)return f[i][j][k];long t = 0;for (int p = 1; p <= m; p++) {if (p > j)  t += dfs(i+1, p, k-1);else        t += dfs(i+1, j, k);}return f[i][j][k] = t % mod;}public int numOfArrays(int n, int m, int k) {f = new long[n][m+1][k+1];this.n = n; this.m = m;for (int i = 0; i < f.length; i++)for (int j = 0; j < f[0].length; j++)Arrays.fill(f[i][j], -1);long res = 0;dfs(0, 0, k);return (int) f[0][0][k];}
}

复杂度分析

  • 时间复杂度:O(nmk)O(nmk)O(nmk),
  • 空间复杂度:O(nmk)O(nmk)O(nmk),

方法三:dp

  • 定义状态

    • f[i][j][k]f[i][j][k]f[i][j][k] 表示前 iii 个数最大数位 jjj 且搜索代价剩余 kkk 时的方案数。
  • 思考初始化:
    • f[0...n][0][0]=1f[0...n][0][0] = 1f[0...n][0][0]=1
  • 思考状态转移方程
    • f[i][j][k]+=fi−1][jj][k]×j,f[i][j][k]\ += fi-1][jj][k] × j,f[i][j][k] +=fi−1][jj][k]×j, 最大值在前 [0,i−1][0, i-1][0,i−1] 个数中,然后第 iii 个数可以选 1−j1-j1−j 中的任意一个而不产生搜索代价。
    • f[i][j][k]+=fi−1][jj][k−1],jj<jf[i][j][k]\ += fi-1][jj][k-1],jj < jf[i][j][k] +=fi−1][jj][k−1],jj<j,也可以在第 iii 个位置选 jjj,那么前 i−1i-1i−1 个数都可以转移到当前状态.
  • 思考输出:f[0][0][k]f[0][0][k]f[0][0][k] 因为状态计算是自底向上的,最后返回到初始状态,这和 dp 稍有不同

自顶向下的 dp 考虑的因素比较多…

class Solution {public int numOfArrays(int n, int m, int K) {int mod = (int) 1e9+7;long f[][][] = new long[n+1][m+1][K+1];f[0][0][0] = 1;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)for (int k = 1; k <= K; k++) {f[i][j][k] += f[i-1][j][k] * j;f[i][j][k] %= mod;for (int jj = 0; jj < j; jj++) {f[i][j][k] += f[i-1][jj][k-1];f[i][j][k] %= mod;}}long res = 0;for (int j = 1; j <= m; j++) {res += f[n][j][K];res %= mod;}return (int) res;}
}

参考大佬的优化思路:在第二个状态转移方程中,我们用了 O(mO(mO(m 的时间求出 [1,j−1][1,j - 1][1,j−1] 转移到的 jjj 和,其实这里可以用一个前缀和 pre[i−1][j−1][k−1]pre[i-1][j-1][k-1]pre[i−1][j−1][k−1] 来记录状态 i,j,k 的前缀和,代办…

复杂度分析

  • 时间复杂度:O(n×m2×k)O(n × m^2 × k)O(n×m2×k),
  • 空间复杂度:O(n×m×k)O(n × m × k)O(n×m×k),

【01 dp】A005_LC_生成数组(暴搜 / 记忆化 / dp)相关推荐

  1. 【线性 dp】A005_LC_不同的子序列(记忆化 / dp 分类讨论)

    一.Problem 给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数. 题目数据保证答案符合 32 位带符号整数范围. 示例 1: 输入:S = "rabbbit ...

  2. [ NOIP提高组 2016]愤怒的小鸟(暴搜 + 状压DP)// [SNOI2017]一个简单的询问(莫队)

    一次性写两道题 T1:一个简单的询问 题目 题解 代码实现 T2:愤怒的小鸟 题目 暴搜题解 暴搜代码实现 状压DP题解 状压DP代码实现 T1:一个简单的询问 题目 给你一个长度为 N 的序列 ai ...

  3. I. Space Station(hash记忆化+dp)

    <文章>陆游 文章本天成,妙手偶得之. 粹然无疵瑕,岂复须人为. 君看古彝器,巧拙两无施. 汉最近先秦,固已殊淳漓. 胡部何为者,豪竹杂哀丝. 后夔不复作,千载谁与期? I. Space ...

  4. 聪聪和可可(记忆化dp+数学期望)

    emmmm 输入格式 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下 ...

  5. 【网格 dp】A002_LC_摘樱桃 I~II 传纸条(基于对角线定理(记忆化 / dp))

    一.摘樱桃 I 一个N x N的网格(grid) 代表了一块樱桃地,每个格子由以下三种数字的一种来表示: 0 表示这个格子是空的,所以你可以穿过它. 1 表示这个格子里装着一个樱桃,你可以摘到樱桃然后 ...

  6. Codeforces Round #459 (Div. 2) C 思维,贪心 D 记忆化dp

    Codeforces Round #459 (Div. 2) C. The Monster 题意:定义正确的括号串,是能够全部匹配的左右括号串. 给出一个字符串,有 (.). ? 三种字符, ? 可以 ...

  7. [区间记忆化dp入门][Bribe the Prisoners SPOJ - GCJ1C09C][Codeforces Round #505D (rated, Div. 1 + Div. 2, ba]

    Bribe the Prisoners SPOJ - GCJ1C09C 作为这类题代表,f[i][j]代表第i点到第j点单独处理的最值 这题关键:释放某个囚犯后,就把囚犯分成两段,两段互相独立 这类d ...

  8. poj 1191 棋盘分割(记忆化dp+递归)

    根据这2个公式可以 得到 O^2 = sum(x1^2 + x2^2 + x3^2 +...xi^2)/n - 平均值^2 所以我们就是要使得总分的平方和尽量小-- 对于一次切割,可以横着切,可以竖着 ...

  9. P4799 [CEOI2015 Day2]世界冰球锦标赛(折半暴搜)

    题目很明确,不超过预算的方案数.两个直觉:1.暴搜2.dp 每个点两种状态,选或不选.... 1.可过20% 2.可过70% 正解:折半搜索(meet in the middle) 有点像以前的双向广 ...

最新文章

  1. 【通知】2021-2022-1线性代数课程答疑安排
  2. 孙正义看未来30年:这个趋势,永远不会错(附完整PPT)
  3. Mybatis是如何实现SQL语句复用功能的?
  4. FD32 查询客户信贷管理中,销售值是怎么来的?
  5. 【转】80后安稳上班,90后看心情上班,95后……太形象了!
  6. Base64编码运用与基本原理
  7. java中如何设置浏览器宽度_[Java教程]关于JS中获取浏览器高度和宽度值的多种方法(多浏览器)_星空网...
  8. selenium的安装
  9. python switch高效替代_python 中无switch(写了几个函数代替switch)
  10. Unity3D使用经验总结 编辑器扩展篇【转】
  11. 默认情况下安装的应用程序C盘后提示权限不足,当你开始介意。。。
  12. 马化腾入选《财富》领袖50强;微博出海布局AI;Android手机爆发病毒 | 一周业界事...
  13. Java中J.U.C扩展组件之ForkJoinTask和ForkJoinPool
  14. keil5.34设置GB2312编码后,字体不能改
  15. 产品经理认证(NPDP)---新产品流程
  16. 基于sklearn的文本特征提取与分类
  17. opencl入门介绍
  18. Eclipse怎样改变字体大小
  19. 用计算机怎么计算p级数,2020考研计算机数学49个基础知识点
  20. ktkkt的视频怎么下载

热门文章

  1. MySQL —— 14、触发器
  2. python 暴力破解 excel加密文件
  3. Python商品数据预处理与K-Means聚类可视化分析
  4. 十年带队经验,万字长文分享:如何管理好一个程序员团队?
  5. 黑*头条_第8章_爬虫系统搭建
  6. OpenHarmony成长计划学生挑战赛7天打卡活动介绍
  7. 一款简洁的 image-crop.js图片裁剪工具
  8. PDF数字签名与验证
  9. Python gdal库读取tif文件
  10. PHP DES加密解密类