常见应用案例
如[一三年蓝桥杯省赛Java组真题](
)“剪格子”就是采用典型的回溯法思想:
package 一三年省赛真题;
import java.util.Scanner;
public class Year2013_t10 {
static int[][] g;
static int[][] sign;
static int m;
static int n;
static int s=0; //记录格子中元素的总和
static int answer = Integer.MAX_VALUE; //最终格子数
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
m = scanner.nextInt(); //输入格子的宽
n = scanner.nextInt(); //输入格子的高
g = new int[n][m];
sign = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
g[i][j] = scanner.nextInt(); //为格子赋值
s+=g[i][j];
}
}
move(0, 0, 0, 0);
System.out.println(answer);
}
/**
* 记录格子的遍历过程
* @param i 移动的横坐标
* @param j 移动的纵坐标
* @param step 步数
* @param sum 格子中元素的总和
* */
public static void move(int i,int j,int step,int sum) {
//如果该格子坐标不在范围内,或该格子已经走过,则返回
if (i==n||i<0||j<0||j==m||sign[i][j]==1) {
return;
}
// 如果当前数值和是总和的一半
if (sum*2==s) {
answer = Math.min(answer, step); //对格子数(步数)与符合要求的格子数比较,取出最小值
}
sign[i][j] = 1; //对走过的格子进行标记,表示格子已经走过
move(i+1, j, step+1, sum+g[i][j]); //down
move(i-1, j, step+1, sum+g[i][j]); //up
move(i, j-1, step+1, sum+g[i][j]); //left
move(i, j+1, step+1, sum+g[i][j]); //right
sign[i][j] = 0; //将该格子重新置于未走过的状态(回溯算法)
}
}
四、分治法
=========
算法定义
分治法是把一个复杂问题分成两个或很多的相同或相似的子问题,再把子问题分成更小的子问题。直到最后子问题可以简单的直接求解,而原问题的解就是子问题的解的合并。
算法原理
将一个规模较大的问题分解为若干规模较小的子问题,找出各子问题的解,然后把各子问题的解组合成整个问题的解。在求解子问题时,往往继续采用同样的策略进行,即继续分解问题,逐个求解,最后合并解,这种不断用同样的策略求解规模较小的子问题,在程序设计语言实现时往往采用递归调用的方式实现,
解题步骤
分治法的过程主要分为三个步骤,
分解,将原问题分解为若干规模较小,相互独立,与原问题形式相同的子问题;
解决。若子问题规模较小而容易被解决则直接解,否则递归的解各个子问题;
合并。将各个子问题的解合并为原问题的解。
特征和典型的应用场合
问题规模缩小到一定程度就可以容易的解决,可以分解为若干个规模较小的相同问题。利用该问题分解出的子问题的解可以合并为该问题的解,该问题所分解出的各个子问题是相互独立的。
常见应用案例
例如快速排序,从数组a[]中找出第k小的元素。
[分治法详解案例](
)
package 一八年省赛真题;
import java.util.Random;
public class Year2018_Bt5 {
public static int quickSelect(int a[],int l,int r,int k) {
Random rand = new Random();
int p = rand.nextInt(r-l+1) + l;
int x = a[p];
int tmp = a[p]; a[p] = a[r]; a[r] = tmp;
int i = l, j = r;
while (ix) j--;
if (i
五、动态规划法
===========
算法定义
动态规划法用于求解包含重叠子问题的最优化问题的方法,
**其基本思想是:**将原问题分解为相似的子问题,在求解过程中通过子问题的解求出原问题的解,动态规划实际上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态。所以它的空间复杂度要大于其他算法。
算法原理
动态规划法通常以自底向上的方式求解各个子问题,分多阶段进行决策,其基本思想是,按时空特点将复杂问题划分为相互联系的若干个阶段,在选定系统行进方向后,逆着这个行进方向,从终点向始点计算,逐次对每个阶段寻找某种决策,使整个过程达到最优,故又称为逆序决策过程,
解题步骤
其解题过程主要分为两个步骤,
划分阶段,按照问题的时间或空间特征,把问题分为若干个阶段,注意这若干阶段,一定要有顺序或者可排序的(即无后向性);
选择状态,将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来,
特征和典型的应用场合
不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略、将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。最后,考虑采用动态规划的关键在于解决冗余。
常见应用案例
动态规划法的一个典型案例是求解字符串的最大公共子串
最大公共子串长度问题就是:求两个串的所有子串中能够匹配上的最大长度是多少.比如: “abcdkkk” 和"baabcdadabc",可以找到的最长的公共子串是"abcd",所以最大公共子串长度为4.
[“最大公共子串”问题详细分析](
)
public class Year2017_Bt6 {
static int f(String s1,String s2) {
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
int [][]a = new int[c1.length+1][c2.length+1];
// "abcdkkk" 和"baabcdadabc",
int max = 0;
//利用循环来进行动态规划,模拟矩阵中的匹配过程
for (int i = 1; i < a.length; i++) {
for (int j = 1; j < a[i].length; j++) {
//如果两个字符匹配成功
if (c1[i-1]==c2[j-1]) {
a[i][j] = a[i-1][j-1]+1; //填空
//判断当前字符的长度是否大于已经匹配到的串的长度
if (a[i][j]>max) max=a[i][j];
}
}
}
return max; //返回匹配到的最长的字符串
}
public static void main(String[] args) {
int n = f("abcdkkk", "baabcdadabc");
System.out.println(n);
}
}
给大家送一个小福利
资料附送高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、准备面试跳槽、自身职业规划迷茫的朋友们。
**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](
)**
本文已被CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】收录,自学编程路线及系列技术文章等资源持续更新中…
“baabcdadabc”);
System.out.println(n);
}
}
### 最后
给大家送一个小福利
[外链图片转存中...(img-Q6qxlWip-1631262769644)]
资料附送高清脑图,高清知识点讲解教程,以及一些面试真题及答案解析。送给需要的提升技术、准备面试跳槽、自身职业规划迷茫的朋友们。
**[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](
)**
[外链图片转存中...(img-7ecZHmb9-1631262769646)]
> **本文已被[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://codechina.csdn.net/m0_60958482/java-p7)收录,自学编程路线及系列技术文章等资源持续更新中...**