优化爬山法之八皇后问题

### 问题描述,八皇后

算法描述:爬山法,是以当前最优,可能会导致结果陷入到局部最优,所以本代码为改进版本的随机重启的爬山法。让陷入无限循环的对象,直接重启,进入新的

环境进行爬山。形象的将棋盘的每一行,看成山~而所有位置是0-7为所有的点,最优函数,计算的是整个棋盘的皇后碰撞对数。所以,每一次爬山,就是算,哪个位置

可以使得函数最优

初始化:棋盘,以行为例够形象些,然后去想象爬山

public static int[] init_queen(int[] queen_array){
        for (int i = 0; i < queen_array.length; i++) {
            queen_array[i] = (int)(Math.random()*8);
        }
        return queen_array;
    }

爬山函数,准备开始爬山操作

//开始爬山
    public static void begin_climbing(int[] queen_array){
        //将当前爬到最优的地方,是不是每个地方都尝试,然后选择最优解的地方,然后开始随机重启
        //开始爬山之前,对该位置,进行评测,然后,计算换位置后的最优解,然后保存,开始随机下一波爬山
        //位置随机
        int function_key = 0;
        int start_index = 0;
        int climbing_count = 0;
        while(true){
            if (climbing_count==40){
                queen_array=reset_arry(queen_array);
                climbing_count = 0;
            }
            climbing_count++;
            function_key = function(queen_array);
            System.out.println("------------------function = "+function_key);
            //出口已经写好
            if(function_key==0){
                System.out.println("------------------find out array--------------------------");
                for (int i = 0; i < 8; i++) {
                    System.out.print("-"+queen_array[i]+"-");
                }
                System.out.println();
                break;
            }

            int min_Value = queen_array[start_index];//存储的当前下标位置
            int temp = function_key;
            for (int i = 0; i < 8; i++) {
                queen_array[start_index] = i;
                if (temp>function(queen_array)){
                    min_Value = i;
                }
            }
            queen_array[start_index] = min_Value;
            //开始随机重启
            System.out.println("------------------爬山开始--------------------------");
            start_index = (int)(Math.random()*8);
            System.out.println("------------------爬山位置"+start_index+"-----------");
        }
    }

重置函数:就是将当前棋盘打乱,找到打破僵局

public static int[] reset_arry(int[] queen_array){
        queen_array = init_queen(queen_array);
        return queen_array;
    }

最后,这是适应度函数

public static int function(int[] queen_array){
        int count = 0;
        for (int i = 0; i < queen_array.length-1; i++) {
            for (int j = i+1; j < queen_array.length; j++) {
                if (queen_array[i]==queen_array[j]|(j-i)==Math.abs(queen_array[i]-queen_array[j])){
                    count++;
                }
            }

        }

        return count;
    }

所有代码如下:

package Mountain_climbing_slove_eight_queen;

/**
 * @Author CRH
 * @Date 2020/11/17 16:41
 */

/**
 * 传统的爬山法,非常容易走进局部最优,最后走不出来,因为这和其本身的关系相关,针对于爬山法,是讲究当前最优解,没有考虑
 * 全局概念,所以,如果想要最优解,就需要随机重启,意思是,当走到不行了的时候,需要将整个棋盘进行重置,然后接着进行爬山法,最后
 * 会得到最优解。
 */

/**
 * 1.爬山法,将当前每行看成第一个,开始爬山,爬到适当的地方为止,标明其为最OK的点,然后选择随机重启,将下一行进行继续随机重启
 * 2、适应度函数为冲突的对数
 * 3、结束条件是冲突函数为0
 */
public class mountain_climbing_slove_eight_queen {
    //爬山法,以当前最优,并寻找最优解
    public static void main(String[] arg){
        int[] queen_array = new int[8];
        queen_array = init_queen(queen_array);
        begin_climbing(queen_array);
    }
    //初始化棋盘
    public static int[] init_queen(int[] queen_array){
        for (int i = 0; i < queen_array.length; i++) {
            queen_array[i] = (int)(Math.random()*8);
        }
        return queen_array;
    }
    //开始爬山
    public static void begin_climbing(int[] queen_array){
        //将当前爬到最优的地方,是不是每个地方都尝试,然后选择最优解的地方,然后开始随机重启
        //开始爬山之前,对该位置,进行评测,然后,计算换位置后的最优解,然后保存,开始随机下一波爬山
        //位置随机
        int function_key = 0;
        int start_index = 0;
        int climbing_count = 0;
        while(true){
            if (climbing_count==40){
                queen_array=reset_arry(queen_array);
                climbing_count = 0;
            }
            climbing_count++;
            function_key = function(queen_array);
            System.out.println("------------------function = "+function_key);
            //出口已经写好
            if(function_key==0){
                System.out.println("------------------find out array--------------------------");
                for (int i = 0; i < 8; i++) {
                    System.out.print("-"+queen_array[i]+"-");
                }
                System.out.println();
                break;
            }

            int min_Value = queen_array[start_index];//存储的当前下标位置
            int temp = function_key;
            for (int i = 0; i < 8; i++) {
                queen_array[start_index] = i;
                if (temp>function(queen_array)){
                    min_Value = i;
                }
            }
            queen_array[start_index] = min_Value;
            //开始随机重启
            System.out.println("------------------爬山开始--------------------------");
            start_index = (int)(Math.random()*8);
            System.out.println("------------------爬山位置"+start_index+"-----------");
        }
    }
    //重置函数
    public static int[] reset_arry(int[] queen_array){
        queen_array = init_queen(queen_array);
        return queen_array;
    }
    //适应度函数
    public static int function(int[] queen_array){
        int count = 0;
        for (int i = 0; i < queen_array.length-1; i++) {
            for (int j = i+1; j < queen_array.length; j++) {
                if (queen_array[i]==queen_array[j]|(j-i)==Math.abs(queen_array[i]-queen_array[j])){
                    count++;
                }
            }

        }

        return count;
    }
}

结语:共勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值