程序脑袋看数学(-)——第二届阿里巴巴全球数学竞赛试题(预选赛第一轮)4.1题

程序脑袋看数学(-)——第二届阿里巴巴全球数学竞赛试题(预选赛第一轮)4.1题_第1张图片
思路:
1.因种植区域为3×4的矩阵,每个位置的元素都是0或1(二进制数),故所有种树方式,为2^12(即4096)种;
2.迭代所有情形,对条件进行判断;
2.1 迭代思路,将4095到0,分别转化成一个一维二进制数组a并补足12位(如,1为000000000001,4095为111111111111),倒序进行是为了找到最大一个满足条件的种植数;
2.2 将转化的一维二进制数组a放在对应新的二维3*4数组b中,具体规则如下:
a[0]–>b[0][0]
a[1]–>b[0][1]
a[2]–>b[0][2]
a[3]–>b[0][3]
a[4]–>b[1][0]
a[5]–>b[1][1]
a[6]–>b[1][2]
a[7]–>b[1][3]
a[8]–>b[2][0]
a[9]–>b[2][1]
a[10]–>b[2][2]
a[11]–>b[2][3]
2.3 对数组b进行规则校验;
2.4 若数组b满足条件,则统计数组b中元素值为“1”的个数(记最大种植数为满足条件第一个m,并算出最新可能值(2^m-1),以缩小迭代范围);若数组b不满足条件,则进行下一数据迭代;
2.5 判定数组b中元素值为“1”的个数是否为m,若为,则保存;若不为,则继续下一次循环;

/**
 * 
 * @ClassName:CreateTree.java
 * @Description:
 * @time: 2020年4月1日 
 * @author: gyj
 */
public class CreateTree {

    public static void main(String[] args) {
        test();
    }
    
    public static void test(){
        List<char[][]> li = new ArrayList<char[][]>();       
        int maxNo=0;     
        int finishNo=0;
//        for(int i=4095;i>=0&&i>=finishNo;i--){//简写为下面                  2的12次方为4096
        for(int i=4095;i>finishNo;i--){
//            char[][]  finalChar = {{'0','0','0','0'},{'0','0','0','0'},{'0','0','0','0'}};
//            char[][]  c = finalChar;//finalChar.clone()、Arrays.copyOf(, )、"="都属于数组的址传递,我勒个去哟
            char[][]  c = {{'0','0','0','0'},{'0','0','0','0'},{'0','0','0','0'}};
            char[] ch = Integer.toBinaryString(i).toCharArray();            
            for(int le = ch.length;le>0;le--){
                int hangshu= (int) Math.ceil(new Double(le)/4);
                c[hangshu-1][(le-1)%4]=ch[le-1];                
            }
            if(vaildChar(c)){
                
                int treeNo = calculateNum(c);//算出当前'1'的个数
                if(maxNo==0){
                    maxNo=treeNo;
                    finishNo=calculate(maxNo);//算出最小可能值,缩小循环次数
                }
                //当当前'1'的个数与最大种指数相等时,保存
                if(treeNo==maxNo){
                    System.out.println("通过校验且种植数为最大的数字:"+i+
                            ",对应数组为{"+Arrays.toString(c[0])+
                            ","+Arrays.toString(c[1])+
                            ","+Arrays.toString(c[2])+"}");                    
                    li.add(c);
                }
            }
        }
        System.out.println("The max crate tree number is :"+maxNo+",and the max type is :"+li.size());
    }
    
    private static int calculate(int n) {
        if (n == 0)
            return 1;
        return 2 * calculate(n - 1);
    }
    
    /**
     * 
     * @Description: 
     * @param c
     * @return 数字计算
     * @time : 2020年3月19日 
     */
    public static Integer calculateNum(char[][] c){
        int reNum =0;
        for(int i=0;i<3;i++){
            for(int j=0;j<4;j++){
                //注意对char类型运算实际是对其ASCII码值进行运算 0ASCII48 1ASCII49 49+49+48=146
                reNum = reNum+c[i][j]-48;   
            }
        }
        return reNum;
    }
      
    /**
     * 
     * @Description: 规则判定 
     * @param c
     * @return
     * @time : 2020年3月19日 
     */
    public static boolean vaildChar(char[][] c){
        //横向判定
        for(int i=0;i<3;i++){
//            if((c[i][i]+c[i][i+1]+c[i][i+2]>2)||(c[i][i+1]+c[i][i+2]+c[i][i+3]>2)){
            //注意对char类型运算实际是对其ASCII码值进行运算 0ASCII48 1ASCII49 49+49+48=146
            if((c[i][0]+c[i][1]+c[i][2]>146)||(c[i][1]+c[i][2]+c[i][3]>146)){
                return false;
            }
        }
        //竖向判定
        for(int i=0;i<4;i++){
            if(c[0][i]+c[1][i]+c[2][i]>146){
                return false;
            }
        }
        //右斜向判定
        if(c[0][0]+c[1][1]+c[2][2]>146){
            return false;
        }
        if(c[0][1]+c[1][2]+c[2][3]>146){
            return false;
        }
        //左斜向判定
        if(c[0][3]+c[1][2]+c[0][1]>146){
            return false;
        }
        if(c[0][2]+c[1][1]+c[1][0]>146){
            return false;
        }
        return true;
    }

}

你可能感兴趣的:(程序看世界)