案例训练1.22:迷宫问题、唯一分解定理、最大公约数

1.迷宫问题

import java.io.*;

public class Main {
    static  int ysize=30;//y范围
    static int xsize=50;//x范围
    static char[][]arr=new char[ysize][xsize];//存储迷宫
    static boolean[][]help=new boolean[ysize][xsize];//判断此点有没有走过
    static BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static  String len="";//路径
    public static void main(String[] args) throws IOException {
        for(int i=0;i<ysize;i++){
            String s=in.readLine();
            arr[i]=s.toCharArray();
        }
        dfs(0,0);
    }

    private static void dfs(int y,int x) {
        if (!check(y,x)){
           return;
        }
        if(check(y+1,x) && arr[y+1][x]=='0' && help[y+1][x]==false){
            len=len+"D";
            help[y+1][x]=true;
            dfs(y+1,x);
            len=len.substring(0,len.length()-1);
        }
        if(check(y,x-1) && arr[y][x-1]=='0' && help[y][x-1]==false){
            len=len+"L";
            help[y][x-1]=true;
            dfs(y,x-1);
            len=len.substring(0,len.length()-1);
        }
        if(check(y,x+1) && arr[y][x+1]=='0' && help[y][x+1]==false){
            len=len+"R";
            help[y][x+1]=true;
            dfs(y,x+1);
            len=len.substring(0,len.length()-1);

        }
        if(check(y-1,x) && arr[y-1][x]=='0' && help[y-1][x]==false){
            len=len+"U";
            help[y-1][x]=true;
            dfs(y-1,x);
            len=len.substring(0,len.length()-1);

        }
        if (x==49&&y==29){
            System.out.println(len);
            return;
        }
    }

    static  boolean check(int y,int x){//判断此点是否在迷宫里
        return y>=0 && y<ysize && x>=0 && x<xsize;
    }


}

这道题第一步,把迷宫创建出来。创建一个char二维数组,通过BufferedReader的readLine()和to.CharArray()配合循环将题目里的迷宫放入数组

第二步,阅读题目可知,限制点移动的条件有:下个点是否走过,是不是0,在不在迷宫内。我们相应的创造方法来解决这些问题,1.创造boolean类型的二维数组help白表示对应的位置是否走过,boolean类型数组默认是false所以当走过时help元素变成true。2.创造check方法判断该点是否在迷宫中y>=0 && y<ysize && x>=0 && x<xsize。

第三步控制点移动,创建dfs方法,设置起始点时(0,0),之后就是简单的判断可否行走然后再进行运算。这一步里关键的是4个if按题目里的从小到大排,并在将下一个点的help设置为true后运行dfs();可以使最后的总和最小,并且很连贯简介。设置一个字符串用来添加"D","L","R","U",并在dfs()内的dfs()后面将字符串截取,配合上一段dfs(),模仿了路径走不通然后退回的过程。

最后就是到达终点后输出字符串len

这道题关键就是迷宫和二数组的结合条件判断怎么写走错路径返回并选其他路径走的代码怎么写,最重要的是最后一条,现在写完感觉很简单,写的时候很难想到这种方法,现在能写出来也是一种进步。

 static int[][]move={{1,0},{0,-1},{0,1},{-1,0}};
    static String[]str={"D","L","R","U"};
    static String len="";
private static void dsf(int y,int x) {
        if (check(y,x)==false){
            return;
        }
        if(y==ysize&&x==xsize){
            System.out.println(len);
            return;
        }
        for(int i=0;i<4;i++){
            if(check(y+move[i][0],x+move[i][1])&&hlep[y+move[i][0]][x+move[i][1]]==false&&arr[y+move[i][0]][x+move[i][1]]=='0'){
            len=len+ str[i];
            hlep[y + move[i][0]][x + move[i][1]]=true;
            dsf(y+move[i][0],x+move[i][1]);
            len=len.substring(0,len.length()-1);
            }
        }
    }

由于dfs()方法中重复的代码太多且格式相同,可以将重复的代码抽出放入循环里,并将不同的变量放到数组里,根据循环次数的不同进行调用

2.唯一分解定理

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //在数学中,唯一分解定理也称为算术基本定理,是数论的重要定理之一。
        //该定理断言:任何一个大于1的整数n都可以分解成若干个素因数的连乘积
        //如果不计各个素因数的顺序,那么这种分解是惟一的。
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        ArrayList<Integer> list=new ArrayList<>();
        for(int i=2;i<=n/2;i++){
                while (n%i==0) {//如果余0,那就对除剩下的数再取余,解决一个素数可能再n的组数因数里出现多次的问题          
                if(panduan(i)){
                   list.add(i);}
                    n=n/i;
                    if(pandaun(n)){//快捷,如果除剩下的数也是素数,根据唯一分解定理,n的质因子就是这几个,直接将其啊放入list,输出list后return结束代码
                        list.add(n);
                        System.out.println(list);
                        return;
                    }                
            }
        }
        if(n>1){
            list.add(1);
            list.add(n);
            System.out.println(list);

        }
    }
    public  static boolean pandaun(int i){//判断是不是素数
        boolean flag=true;
        for (int j=2;j<i/j;j++){
            if (i%j==0){
                flag=false;
            }
        }
        return flag;
    }
}
在数学中,唯一分解定理也称为算术基本定理,是数论的重要定理之一。该定理断言:任何一个大于1的整数n都可以分解成若干个素因数的连乘积。如果不计各个素因数的顺序,那么这种分解是惟一的。

根据这个特性,可以与昨天的收获“某数的因数的因数是某数的因数结合”,试想一下,根据唯一分解定理,n是由多个素数相乘得到,这几个素数是一定的,而当n被素数x除后得到的数m肯定能被分解成多个素数相乘,那么可知n的因子的素数因子也是他的素数因子,且这些素数因子是在根号n以前的,除非n本身是质数。所以可以用循环,而循环条件就是从i=2开始从小到大对n取余,并内嵌while循环防止一个素数因子可以出现多次的情况被忽略。

个人理解:简单的来想,n于其因子使用的素因子是同样的,且都在n以内,只用把for循环范围上到根号n(因为大于根号n的素数肯定只有一个再根号n之前的数可以与他相乘等于n,座椅只用添加一个对n/i是否为玉树的判断就行了),并添加while循环用防止一个素数因子可以出现多次的情况被忽略。

3.最大公约数

//最大公约数
        Scanner sc=new Scanner(System.in);
        int a=sc.nextInt();
        int b=sc.nextInt();
        int temp=Math.max(a,b);
        int count=Math.min(a,b);
        int t=1;
        while (t!=0){
          t=temp%count;
           temp=count;
           count=t;
        }
        System.out.println(temp);

运用数学思维,把a和b看成一个长方形的长宽,具体思路难以言喻,跟着代码带入长方形就能感悟到了

4.总结

今天的收获主要在于做迷宫问题时对二维数组的应用更加精巧,以及设计思路的扩展,比如迷宫问题里dfs()方法模仿了路径走不通退回并重新的过程,以及唯一分解定理中对数学思维的扩展,使解决问题使变得更加具体。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值