三维一般使用dp记忆化搜索就能过leetcode了,想要优化可以改成位置依赖版本
474. 一和零
已解答
中等
给你一个二进制字符串数组 strs
和两个整数 m
和 n
。
请你找出并返回 strs
的最大子集的长度,该子集中 最多 有 m
个 0
和 n
个 1
。
如果 x
的所有元素也是 y
的元素,集合 x
是集合 y
的 子集 。
示例 1:
输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3 输出:4 解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。 其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。
static int [][][] dp; public static int findMaxForm(String[] strs, int m, int n) { //来到index位置,两种情况 要或者不要 dp = new int[n+1][m+1][strs.length]; for (int i = 0;i<n+1;i++){ for (int j = 0;j<m+1;j++){ Arrays.fill(dp[i][j],-1); } } return process(strs,m,n,0); } public static int process(String[] strs, int m, int n,int index){ if(index==strs.length){ return 0; } //来到index位置,两种情况 要或者不要 if(dp[n][m][index]!=-1){ return dp[n][m][index]; } int p1 = process(strs,m,n,index+1); int ncnt = 0; int mcnt = 0; for(int i = 0;i<strs[index].length();i++){ if(strs[index].charAt(i)=='1'){ ncnt++; } } mcnt = strs[index].length()-ncnt; int p2 = 0; if(n-ncnt>=0&&m-mcnt>=0){ p2 = process(strs,m-mcnt,n-ncnt,index+1)+1; } dp[n][m][index] = Math.max(p1,p2); return dp[n][m][index]; }
879. 盈利计划
已解答
困难
集团里有 n
名员工,他们可以完成各种各样的工作创造利润。
第 i
种工作会产生 profit[i]
的利润,它要求 group[i]
名成员共同参与。如果成员参与了其中一项工作,就不能参与另一项工作。
工作的任何至少产生 minProfit
利润的子集称为 盈利计划 。并且工作的成员总数最多为 n
。
有多少种计划可以选择?因为答案很大,所以 返回结果模 10^9 + 7
的值。
示例 1:
输入:n = 5, minProfit = 3, group = [2,2], profit = [2,3] 输出:2 解释:至少产生 3 的利润,该集团可以完成工作 0 和工作 1 ,或仅完成工作 1 。 总的来说,有两种计划。
public static int mod = 1000000007; static long [][][] dp ; public static int profitableSchemes(int n, int minProfit, int[] group, int[] profit) { dp = new long[minProfit+1][n+1][profit.length]; for (int i = 0;i<minProfit+1;i++){ for (int j = 0;j<n+1;j++){ Arrays.fill(dp[i][j],-1); } } return process(minProfit,group,profit,n,0); } private static int process(int minProfit, int[] group, int[] profit, int rest, int i) { //如果目标达成,返回1种 if(i==group.length){ return minProfit==0 ? 1:0 ; } if (dp[minProfit][rest][i]!=-1){ return (int)dp[minProfit][rest][i]; } //当前做或者不做 long ans = process(minProfit,group,profit,rest,i+1)%mod; int newrest = rest-group[i]; if (newrest>=0){ ans=(ans+process(Math.max(minProfit-profit[i],0),group,profit,newrest,i+1))%mod; } dp[minProfit][rest][i] = ans; return (int) ans%mod; }
688. 骑士在棋盘上的概率
已解答
中等
相关标签
相关企业
在一个 n x n
的国际象棋棋盘上,一个骑士从单元格 (row, column)
开始,并尝试进行 k
次移动。行和列是 从 0 开始 的,所以左上单元格是 (0,0)
,右下单元格是 (n - 1, n - 1)
。
象棋骑士有8种可能的走法,如下图所示。每次移动在基本方向上是两个单元格,然后在正交方向上是一个单元格。
每次骑士要移动时,它都会随机从8种可能的移动中选择一种(即使棋子会离开棋盘),然后移动到那里。
骑士继续移动,直到它走了 k
步或离开了棋盘。
返回 骑士在棋盘停止移动后仍留在棋盘上的概率 。
示例 1:
输入: n = 3, k = 2, row = 0, column = 0 输出: 0.0625 解释: 有两步(到(1,2),(2,1))可以让骑士留在棋盘上。 在每一个位置上,也有两种移动可以让骑士留在棋盘上。 骑士留在棋盘上的总概率是0.0625。
public static void main(String[] args) { System.out.println(knightProbability(3, 2, 0, 0)); } static int [] movex = new int[]{1,2,2,1,-1,-2,-2,-1}; static int [] movey = new int[]{2,1,-1,-2,2,1,-1,-2}; static double [][][]dp = new double[101][25][25]; public static double knightProbability(int n, int k, int row, int column) { for (int i =0;i<n;i++){ Arrays.fill(dp[0][i],1); } for (int i = 1;i<=k;i++){ for (int j = 0;j<n;j++){ for (int l = 0;l<n;l++){ double ans = 0; int nrow; int ncol; for (int index = 0;index<movex.length;index++){ nrow = j+movex[index]; ncol = l+movey[index]; if (nrow>=n||nrow<0||ncol>=n||ncol<0){ continue; } ans+=dp[i-1][nrow][ncol]/8; } dp[i][j][l] = ans; } } } return dp[k][row][column]; }
2435. 矩阵中和能被 K 整除的路径
已解答
困难
相关标签
相关企业
提示
给你一个下标从 0 开始的 m x n
整数矩阵 grid
和一个整数 k
。你从起点 (0, 0)
出发,每一步只能往 下 或者往 右 ,你想要到达终点 (m - 1, n - 1)
。
请你返回路径和能被 k
整除的路径数目,由于答案可能很大,返回答案对 109 + 7
取余 的结果。
示例 1:
输入:grid = [[5,2,4],[3,0,5],[0,7,2]], k = 3 输出:2 解释:有两条路径满足路径上元素的和能被 k 整除。 第一条路径为上图中用红色标注的路径,和为 5 + 2 + 4 + 5 + 2 = 18 ,能被 3 整除。 第二条路径为上图中用蓝色标注的路径,和为 5 + 3 + 0 + 5 + 2 = 15 ,能被 3 整除。
示例 2:
输入:grid = [[0,0]], k = 5 输出:1 解释:红色标注的路径和为 0 + 0 = 0 ,能被 5 整除。
//这里只给出递归函数,在方法函数调用即可 private static int process(int[][] grid, int x, int y,int sum,int k) { if (x==grid.length-1&&y==grid[0].length-1){ sum=(sum+grid[x][y])%k; dp[x][y][sum] = sum%k==0 ? 1:0; return(int) dp[x][y][sum]; } sum=(sum+grid[x][y])%k; if (dp[x][y][sum]!=-1){ return(int) dp[x][y][sum]; } long ans = 0; if (x+1<grid.length){ ans=(ans+process(grid,x+1,y,sum,k))%mod; } if (y+1<grid[0].length){ ans=(ans+process(grid,x,y+1,sum,k))%mod; } ans = ans%mod; dp[x][y][sum] = ans; return (int) ans; }