算法—熟悉环境和递归算法

一、实验目的

1 )熟悉 Java 上机环境;
(2)基本掌握递归算法的原理方法。

二、实验内容

1、将正整数 n 表示成一系列正整数之和: n=n1+n2+…+nk, 其中 n1≥n2≥…≥nk
≥1,k≥1。正整数 n 的这种表示称为正整数 n 的划分。求正整数 n 的不同划分个
数。
2、设计一个递归算法生成 n 个元素{r1,r2,…,rn}的全排列。
3、Hanoi 塔问题
     设 a,b,c 是 3 个塔座。开始时,在塔座 a 上有一叠共 n 个圆盘,这些圆盘自下而上,
由大到小地叠在一起。各圆盘从小到大编号为 1,2,…,n,现要求将塔座 a 上的圆盘移到
塔座 b 上,并仍按同样顺序叠置。在移动圆盘时应遵守以下移动规则:
     规则 1:每次只能移动 1 个圆盘;
     规则 2:任何时刻都不允许将较大的圆盘压在较小的圆盘之上;
     规则 3:在满足移动规则 1 和 2 的前提下,可将圆盘移至 a,b,c 中任一塔座上。

 三、实验步骤

1 、题目一
(1) 问题分析
      第一个实验:整数划分问题使用递归来求解,设 p(n)为正整数 n 的划分数,分析问题,因为难以找到递归关系,需要增加一个自变量将最大加数 n1 不大于 m 的划分个数记作 q(n,m),就可以建立它的递归关系。通过对 n,m 关系的讨论, 可以得出 q(n,m)的递归式:
当 n=1,m=1 时 q(n,m)=1; 当 n<m 时,q(n,m)=q(n,n); 当 n=m 时,q(n,m)=1+q(n,n-1); 当 n>m>1 时,q(n,m)=q(n,m-1)+q(n-m,m)。 由递归式便可以设计 q(n,m)的递归算法。算法中正整数 n 的划分数 p(n)= q (n,n)。
(2) 算法描述
package liujinchan;
import java.util.Scanner;
public class number {
public static void main(String []args) {
System.out.println("请输入一个正整数n: ");
Scanner input=new Scanner(System.in);
int n=input.nextInt();
System.out.println("n的不同划分个数为:"+q(n,n));
}
public static int q(int n,int m)
{
if((n<1)||(m<1))
return 0;
if((n==1)||(m==1))
return 1;
if(n<m)
return q(n,n);
if(n==m)
return q(n,m-1)+1;
return q(n,m-1)+q(n-m,m);
}
}
(3) 运行结果
     

 2、题目二

2 、题目二
(1) 问题分析
      首先了解一下全排列(perm):从 n 个不同元素中任取 m(m<=n)个元素, 按照一定的顺序排列起来,叫做从 n 个不同元素中取出 m 个元素的一个排列,当 m=n 时,所有的排列情况就叫做全排列。 用递归的方法来求解。设 R={r1,r2,…rn}是要进行排列的 n 个元素, Ri=R-{ri}。集合 X 中元素的全排列记为 perm(X)。(ri)perm(X)表示在全排 列 perm(X)的每一个排列前加上前缀 ri 得到的排列。R 的全排列可归纳定义如 下: 当 n=1 时,perm(R)=(r),其中 r 是集合 R 中唯一的元素; 当 n>1 时,perm(R)由(r1)perm(R1),(r2)perm(R2),…(rn)perm (Rn)构成。依此递归定义,可以设计出 perm(R)的递归算法。
(2) 算法描述
package liujinchan;
import java.util.Scanner;
public class Perm {
public static void main(String []args) {
System.out.println("请输入全排列元素的个数为: ");
Scanner input=new Scanner(System.in);
int a=input.nextInt();
Object[] list=new Object[a];
for(int i=0;i<list.length;i++) {
list[i] = i+1;
}
FullArray(list,0,list.length-1);
}
public static void FullArray(Object [] list,int k,int m) {
if(k==m) {
for(int i=0;i<=m;i++) { 
System.out.print(list[i]);
}
System.out.println();
}
else {
for(int i=k;i<=m;i++) {
swap(list,k,i);
FullArray(list,k+1,m);
swap(list,k,i);
}
}
}
public static void swap(Object[]list,int k,int i) {
Object temp;
temp=list[k];
list[k]=list[i];
list[i]=temp;
}
}
(3) 运行结果

 

3 、题目三
(1) 问题分析
     采用递归技术来实现。 当 n=1 时,只要将编号为 1 的圆盘从塔座 a 直接移至塔座 b 上即可。
n>1 时,需要利用塔座 c 作为辅助塔座。此时若能设法将 n-1 个较小的圆 盘依照移动规则从塔座 a 移至塔座 c ,然后,将剩下的最大圆盘从塔座 a 移至塔 座 b ,最后,再设法将 n-1 个较小的圆盘依照移动规则从塔座 c 移至塔座 b 。 由此可见,n 个圆盘的移动问题可分为两次 n-1 个圆盘的移动问题,这又可 以递归地用上述方法来做。
(2) 算法描述
package liujinchan;
import java.util.Scanner;
public class Hanoi {
public static void main(String[] args) {
Hanoi hanoi=new Hanoi();
System.out.println("请输入一个圆盘数n:");
Scanner input=new Scanner(System.in);
int n=input.nextInt();
hanoi.hanoi(n, 'A', 'B', 'C');
}
public static void hanoi(int n, int a, int b,int c) {
if(n>0) {
hanoi(n-1, a, c, b);
move(a,b);
System.out.println("第" + n + "个盘从 " + (char)a + "->" +(char)b);
hanoi(n-1, c, b, a);
}
}
private static void move(int a, int b) {
// TODO Auto-generated method stub
}
}
(3) 运行结果

四、出现的问题及解决的方法

在实验一中:
①在写完代码后发现运行不出结果,代码也没有报错,语法没有问题,从开始到
最后仔仔细细的检查了一遍,才发现自己粗心将 main 写成了 mian,代码并不会报错,
但是不会运行。
在实验二中:
①在测试代码的时候发现输出的结果怎么样都不对,代码中检查了一遍又一遍,
查看了书中的展示的代码,又去找了课堂回放,终于发现是自己将 for 中的条件 i<=m
少写了一个等号,这直接就导致输出的结果大相径庭而且还不容易发现。真的是自己
的粗心大意,下次一定要更加细心。
②在解决问题后,发现控制台输出的效果实在是不美观,每一组排列都是换行输
出,看着十分别扭,也不容易分辨。在上网搜查后才发现自己的知识漏洞:print 不带
换行输出,而 println 带换行输出,在运行代码过程中能庆幸自己可以查缺补漏。
在实验三中:
①一开始的时候将输出的结果写在 move 函数中,但是发现如果这样的话结果不能
展示出第 n 个盘子的移动,因为老师强调过需要展示一个第 n 个盘子从哪移动到哪的
结果,所以做出了改变,将输出结果写在了 move 函数的后边
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FineFINE01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值