分治:把问题分为多个子问题 求出子问题的解 合并就为问题的解 (分治中每个子问题之间不存在相互依赖) 案例汉诺塔
public class FenZhi {
public static void main(String[] args) {
hnt(3,'A','B','C');
}
//汉诺塔
public static void hnt(int count,char a,char b,char c ){
if (count==1){
System.out.println("移动第:"+count+"块,从"+a+"->"+c);
return;
}
//count = 3 进入 hnt(count=2 , a . c , b) 在count等于2这个空间中 b是c c是b
// 然后再hnt(count=1,a,c,b)
// 在count等于1时cb再次互换 使得他们恢复自己 b=b c=c 此时count = 1
// 然后触发if条件输出第1个从a - c (因为此时cb的值经过两次调换恢复了本来的值)再触发return
//然后回溯到count=2 这个空间中 然后向下运行输出“System.out.println("移动第:"+count+"块,从"+a+"->"+c);” 这个语句
//在count=2这个空间中cb的值是互换的 所以输出第2个从a-b
// 然后继续向下 执行hnt(count-1,b,a,c); 再次开辟一个count = 1的空间并调换当前b(当前b的值为c)跟当前a的值
//然后再次触发if 然后输出第一个盘从a(a此时为b的值 而b此时为c的值 所以a=c) - c(c此时为b的值) 实际输出c -b;再触发return
// 然后回溯至count=2这个空间 发现这个空间已执行完毕
//再次回溯至count = 3这个空间 然后向下运行 " System.out.println("移动第:"+count+"块,从"+a+"->"+c);" 此时abc的值是正常的
//所以输出第3块从a-c 然后 执行“hnt(count-1,b,a,c);”
// 再次开辟count = 2的空间并调换ab的值 在新开辟的count =2的空间中 再次执行hnt(count-1,a,c,b);
//再次开辟count = 1的空间并调换现在b(此时表示a) - c的值
//在新开辟的count = 1这个空间中 a=b b = c c = a 然后触发if输出第1块从a(b) - c(a) 即b - a
//然后再次回溯至count = 2的空间中向下执行 此时a=b b=a c=c 再次输出a(b)-c 实际b-c
//然后再次开辟count=1的空间 并调换当前a-b的值 此时(新的count=1的空间中) a=a b=b c=c
// 因为他是在a=b b=a c=c的情况下调换的ab的值 所以恢复了
//然后触发if语句 输出第1块从a - c 再触发return 然后回溯至count = 2的空间 发现此空间执行完毕
// 再回溯至count=1的空间中 发现这个空间也执行完毕 所以方法停止
hnt(count-1,a,c,b);
System.out.println("移动第:"+count+"块,从"+a+"->"+c);
hnt(count-1,b,a,c);
}
}
动态规划:与分治相似 但动态规划分解出的子问题之前 是需要相互依赖的
案例 01背包问题
package DynamicPlanning;
public class backPack {
public static void main(String[] args) {
//01背包问题 - 动态规划
int []weight = {1,3,4};//商品所占用的重量
int []value = {1500,2000,3000};//商品的价值
int m = 4;//背包的最大容量
int n = value.length;//商品的数量(种类数量)
//用来求结果 有物品的种类数量+1行 每一行都表示一个商品 +1是因为有第0行 0行代表没有商品
//有当前背包最大容量+1列 也是有第0列 dp[][] 代表当前背包容量和当前商品种类数量的情况下 背包装入的最大价值
//设置背包 这个步骤可以忽略 因为数组的初始值就是0 这个步骤代表吧商品数量为零的时候的所有背包容量的情况全部为0
int [][]dp = new int[n+1][m+1];
//该数组用来记录你装入了那个商品
int [][]sp = new int[n+1][m+1];
for (int i=0;i<n+1;i++){
dp[i][0] = 0;
}
for (int i=0;i<m+1;i++){
dp[0][i] = 0;
}
//填充表格情况 求结果 不遍历第0行和第0列的情况 因为结果一定为0
for (int i=1;i<dp.length;i++){
for (int j = 1; j < dp[i].length; j++) {
//如果当前商品的重量 > 当前背包的重量 也就是当前商品无法放入当前背包
if (weight[i-1] > j){//因为dp中有0的存在而weight中没有 所有这里要-1 j代表当前背包的容量
dp[i][j] = dp[i-1][j];//那么dp[当前商品数量][当前背包容量]的价值 就等于dp[上一个商品数量][当前背包容量]的价值
}else{//否则就是 当前商品的重量=或者<当前背包容量
//如果 dp[上一个商品数量][当前背包容量]的价值 < 当前这个商品的价值 + dp[上一个商品数量][(当前背包容量 - 当前商品重量)]的价值
if (dp[i-1][j] < value[i-1] + dp[i-1][j-weight[i-1]]){
//dp = 当前这个商品的价值 + dp[上一个商品数量][(当前背包容量 - 当前商品重量)]的价值
dp[i][j] = value[i-1] + dp[i-1][j-weight[i-1]];
//表示 这个时候装入了当前商品
sp[i][j] = 1;
}else{
dp[i][j] = dp[i-1][j];
}
}
}
}
for (int i=0;i<dp.length;i++){
for (int j = 0; j < dp[i].length; j++) {
System.out.print(dp[i][j]+"\t");
}
System.out.println();
}
System.out.println("装入情况");
for (int i=0;i<sp.length;i++){
for (int j = 0; j < sp[i].length; j++) {
System.out.print(sp[i][j]+"\t");
}
System.out.println();
}
int x = n;//商品的种类数量
int y = m;//背包的最大容量
while (x>0&&y>0){
if (sp[x][y] == 1){
System.out.println("装入了商品"+x);
y = y - weight[x-1];
}
x--;
}
}
}