算法设计与分析:整数划分->汉诺塔
整数划分
转载及参考声明
本文大部分转载自CSDN-@tyilack_小小黑
另有菜鸟教程
其他参考:
https://blog.csdn.net/li_ya_fei/article/details/84725057
https://iowiki.com/java/util/scanner_hasnextint_radix.html
https://blog.csdn.net/qq_41718454/article/details/104733740
在递归的时候进行结果输出这个问题看似简单,但是执行起来不容易(for me),别笑
题目:
分析:
为了测试算法的正确性,我们带入题目给出的求正整数6划分个数来验证。一开始划分数为0。正整数6可以由一些加数通过加法相加来得到,为了方便分析,先把这些加数的集合定义为A。
第一步:带入q(6,6),进入函数之后,符合n = = m这中情况,那么此时首先是增加了第一种情况,就是集合A中最大的加数为6的时候,只有一种情况,即6 = {6},在划分数加1之后,继续递归计算集合A中最大加数为5的所有划分个数,也就是q(6,5)。所以当n = = m时,公式:q(n,m) = 1 + q(n, n-1)是正确的。
第二步:这一步计算的是q(6,5),符合第四种情况(n>m>1)。当集合A中最大加数已经确定是5之后,那么只需要计算6-5=1不大于5的所有划分数就是整数6的所有以5开头的加法因子的划分数,也就是q(1,5)。在计算最大加数为5的划分数之后,还需要继续递归计算最大加数为4的划分数,也就是q(6,4)。所以当n>m>1时,公式q(n,m) = q(n,m-1) + q(n-m,m)是正确的。
第三步:因为上一步有两个递归公式,首先先考虑q(n-m,m)也就是q(1,5),当最大加数为1的时候,由情况一可以知道只有加数是1这一种情况,在这里就可以确定集合A中一最大加数为5开头的所有划分情况只有一种,就是6={5+1}。这里有根据公式q(n,m) = q(n,m-1) + q(n-m,m)接着把q(6,4)划分为q(6,3)+q(6-4,2)。
后面的情况几乎和前面3步分析的情况差不多。所以我们可以根据上面的递归公式来计算出任意一个正整数的所有划分数。但是题目还需要打印所有划分的情况,那么我们可以定义一个全局数组变量int a[],来记录每一个加数,所以我们可以把上述所说的递归方程q(n,m)改成q(n,m,i),这里的i表示数组a的下标,那么在每一次递归方法中,第一个操作就是赋值给数组,也就是执行操作a[i]=m。
代码上菜
package com.htu.test;
import java.util.Scanner;
public class ZhengShuHuaFen {
static int[] a = new int[1000];//静态数组a用来装每一个小列表
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
while(in.hasNextInt()) {//检测输入内容是否为数字
int n = in.nextInt();
int count = q(n, n, 0);//count就是题中的p(n),是总的结果种类数,i从0开始,由于是递归,传一次参数就够了
System.out.println(count);
}
}
//递归函数q(n,m,i),这里比书上多了i,目的是为了打印具体划分情况,而且每次都是在return调用之前打印当前情况
public static int q(int n, int m, int i) {
if(n < m) {//m给的过头了就要收缩
return q(n, n, i);
}
a[i] = m;//在经过了上面的的if检测之后,接下来的m就是“合格的”m了,即m<=n,把m存起来,当然m是会变的,不过i也在变
//我们要达到的效果就是每个小列表[m,......]
if(n == 0 || m == 0) {
//打印下标从0到i
printPartition(i);
return 0;
}
if(n == 1 || m == 1) {
if(n == 1) {
//打印下标从0到i
printPartition(i);
}
else q(n-1, 1, i+1);
return 1;
}
if(n == m) {
//打印下标从0到i
printPartition(i);
return 1 + q(n, n-1, i);
}
return q(n-m, m, i+1) + q(n, m-1, i);//i+1代表小列表里面的下一位
}
//展示分类的具体结果,i其实就是每个小列表[]里面的分子数,比如[5+1]里面的5或1
public static void printPartition(int i) {
System.out.print("[");
//只要有结果列表,内部必是循环
//功能:对a数组从0打印到i
for(int j = 0; j <= i; j++) {
if(j == i) System.out.print(a[j]);//打印小列表里面的最后一个小数字
else System.out.print(a[j] + "+");
}
System.out.println("]");
}
}
汉诺塔
对于题目我就不引用了,毕竟个人笔记嘛,若是不小心看到这个文章,见谅哈
package cn.htu.test;
public class Hanoi {
public static void main(String[] args) {
int nDisks = 3;//总的碟片数
doTowers(nDisks, 'A', 'B', 'C');
}
//topN的寓意其实就是每次要挪的碟片,至于挪动的过程建议看一下小甲鱼的动画,理解更深刻
//from是挪动源
//to是挪动目标位置
//inter是中间,就是通过谁去挪
public static void doTowers(int topN, char from, char inter, char to) {
if (topN == 1){
System.out.println("Disk 1 from "
+ from + " to " + to);
}else {
doTowers(topN - 1, from, to, inter);
System.out.println("Disk "
+ topN + " from " + from + " to " + to);
doTowers(topN - 1, inter, from, to);
}
}
}
原文地址:https://www.cnblogs.com/shallow920/p/12883521.html
- 100w条记录分页,可以有多快?—— DataReader分页与SQL语句分页的对比测试(在线演示)
- Mimikatz小实验:黄金票据+dcsync
- 【自然框架】n级下拉列表框的原理
- 【自然框架】分享 n级联动下拉列表框
- GSM Hacking Part ②:使用SDR捕获GSM网络数据并解密
- 【自然框架】之数据访问 —— 再小的类库也需要设计。
- 【自然框架】之表单控件(一)实体类(Class)VS 字典(Dictionary)
- 跨平台后门Mokes现已加入OS X豪华午餐
- 【问底】严澜:数据挖掘入门——分词
- 机器学习-简单线性回归教程
- NSA(美国国安局)泄漏Exploit分析
- 详解Windows Shim的攻防利用
- 基于Github的源码白盒扫描工具Raptor
- 把业务逻辑变成数据结构和SQL语句的例子。自然架构改成自然框架
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MySQL 复制全解析 Part 11 使用xtrabackup建立MySQL复制
- windows之NTLM认证
- 3A之自动白平衡(AWB)篇
- 欧拉角旋转
- matplotlib中文乱码的两种解决方案
- MySQL MHA部署 Part 3 MHA软件安装
- 自然语言处理的基本要义:向量表示法
- MySQL MHA部署 Part 4 MHA部署前准备
- 【NPM库】- 0x04 - Mock Data
- docker上部署MySQL实例
- Tomcat 高并发之道原理拆解与性能调优
- Redis运维之swap空间
- MySQL组复制(MGR)全解析 Part 4 MGR单主模式部署前准备
- Spring 中的自动装配
- antlr4入门篇