蓝桥杯国赛之六角幻方

题目:六角幻方

把 1 2 3 … 19 共19个整数排列成六角形状,如下:

    * * *
   * * * *
  * * * * *
   * * * * 
    * * *

要求每个直线上的数字之和必须相等。共有15条直线哦!

再给点线索吧!我们预先填好了2个数字,第一行的头两个数字是:15 13,参见图【p1.png】,黄色一行为所求。

请你填写出中间一行的5个数字。数字间用空格分开。

这是一行用空格分开的整数,请通过浏览器提交答案,不要填写任何多余的内容(比如说明性的文字等)

答案:

import java.util.Scanner;  

public class Main {  
//  把19个数装入table数组中
    public static int [] table = {1,2,3,4,5,6,7,8,9,10,11,12,14,16,17,18,19};  
//    数的最大值
    public static final int rang = table.length;  
//    用flag来标记当前的数字是否被用过
    public static boolean [] flag = new boolean [rang];  
//    用array来装选中的数字
    public static int [] array = new int [rang];  
//    public static int n;  
    public static int count;  

    public static void Permutation(int k) {  
        if(k == 5){  
            if(array[0]+28 != array[1]+array[2]+array[3]+array[4])  
                return;  
        }  
        if(k == 6){  
            if(array[0]+28 != 15+array[1]+array[5])  
                return;  
        }  
        if(k == 10){  
            if(array[0]+28 != array[0]+array[4]+array[9])  
                return;  
            if(array[0]+28 != array[5]+array[6]+array[7]+array[8]+array[9])  
                return;  
        }  
        if(k == 11){  
            if(array[0]+28 != 13+array[2]+array[6]+array[10])  
                return;  
        }  
        if(k == 14){  
            if(array[0]+28 != array[10]+array[11]+array[12]+array[13])  
                return;  
            if(array[0]+28 != 13+array[3]+array[8]+array[13])  
                return;  
        }  
        if(k == 17){  
            if(array[0]+28 != array[14]+array[15]+array[16])return;    
            if(array[0]+28 != array[5]+array[10]+array[14])return;  
            if(array[0]+28 != array[9]+array[13]+array[16])return;  
            if(array[0]+28 != array[0] +array[3]+array[7]+array[11]+array[14])return;  
            if(array[0]+28 == 13+array[3]+array[8]+array[13]){  
                System.out.println(array[5]+" "+array[6]+" "+array[7]+" "+array[8]+" "+array[9]);  
                count++;  
                return;  
            }  
        }  
        for(int i = 0; i < rang; i++){  
//          用flag来判断当前数字是否被用过了,如果没有用过,就选择table[i]加入array[k]中。
//          当k = 0的时候,刚好选好第0位的数字;一共有17个数字要选;第0位到第16位;所以要比较前两行的和,就是要选好第4位的数,而且一般来说递归都放在方法的后部
//          if比较,返回--for + flag[]选择,记录--递归--还原
//          选好第4位,记录flag后,要if比较,就要进入下一层递归,在下一层递归的前部,进行比较。
//          所以说,选好第4位后,要比较前两行的和,此时,k == 5;以此类推,选好第16位后,要比较前五行的和,此时,k == 17.
            if(!flag[i]){  
//              k 的意思就是   本层递归要选取第几个位置的数字
//              for循环遍历flag数组,利用当前遍历到的flag[]中的false的索引,在table[]中选取相应的元素,将其赋给array[]中第k个位置。
                array[k] = table[i];  
//              
                flag[i] = true;  
                Permutation(k+1);  
                flag[i] = false;  
            }  
        }  
    }  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
//        System.out.println(System.currentTimeMillis());  
        Permutation(0);  
//        System.out.println(count);  
//        System.out.println(System.currentTimeMillis());  
    }  


}  

心得:

递归型DFS;两个数组的索引相关联 boolean [] flag 、int [] table

猜你喜欢

转载自blog.csdn.net/qq_37905259/article/details/80569905