洛谷 P1219 八皇后(搜索 java实现)

在这里插入图片描述

     这题用到的思路就是深搜,但是深搜还是需要点优化,不然会超时。

 	 for(int i=1;i<=n;i++) {
            boolean flag=false;
            if(!book[i]) {
                for(int j=1;j<step;j++) 
                    if(step-j==Math.abs(i-nums[j])) {
                        flag=true;
                        break;
                    }
                }
                if(flag==true)
                    continue;
                nums[step]=i;
                book[i]=true;
                dfs(nums,step+1,n);
                book[i]=false;
            }
        }

    先说明一下变量都代表的什么意思,因为题目中行是默认升序的,我们只需要判断应该在哪一列就行,用i来遍历所有的列,j是来遍历所有的行,step表示是到达了第几行,nums数组的下标表示行数,下标对应的数组元素表示棋子放在该行的哪一列。

 			for(int j=1;j<step;j++) 
                    if(step-j==Math.abs(i-nums[j])) {
                        flag=true;
                        break;
                    }
                }

    上边的代码就是对角线的判断,对角线判断条件是 行-行==列-列,如果满足这个条件,表示在同一个对角线上,就不能要,从第一行开始判断,如果第step行-第j行 == 第i列-第j列的绝对值,因为step肯定比j大,所以不用带绝对值,而列数不一样,有可能第一行在最后一列,第二行在第三列这种情况,所以列数的差需要带个绝对值。

 				if(flag==true)
                    continue;
                nums[step]=i;
                book[i]=true;
                dfs(nums,step+1,n);
                book[i]=false;

    如果flag==true表示构成了对角线,所以就continue,到下一列,如果没有对角线,说明这个点是可以进入nums数组的,将其添加进去,并且标记这个点已经走过,接着遍历下一行,返回的时候要把标记去掉。

import java.util.*;

public class Main {
    static boolean[] book;//用来表示是否访问过
    static int cnt=0;
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        book=new boolean[n+1];//下标从1开始,所以就是n+1
        int[] nums=new int[n+1];
        new Main().dfs(nums,1,n);
        System.out.println(cnt);
    }
    void dfs(int[] nums, int step, int n) {
        if(step==n+1) {//说明数字走完了,要退了
            cnt++;
            if(cnt<=3) {//因为只用输出前三个
                for(int i=1;i<=n;i++) {
                    System.out.print(nums[i]+" ");
                }
                System.out.println("");
            }
            return ;
        }
        
        for(int i=1;i<=n;i++) {
            boolean flag=false;
            if(!book[i]) {
                for(int j=1;j<step;j++) {
                    if(step-j==Math.abs(i-nums[j])) {
                        flag=true;
                        break;
                    }
                }
                if(flag==true)
                    continue;
                nums[step]=i;
                book[i]=true;
                dfs(nums,step+1,n);
                book[i]=false;
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值