非平凡Java数学练习

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了非平凡Java数学练习相关的知识,希望对你有一定的参考价值。

我被问到这个问题来测试我的编程能力。虽然我觉得它和编程一样多。老实说我失败了,但我想知道它是如何做的,以备将来参考。

理想的答案将使用递归和线程。

你的侄女为她的生日提供了一套积木,她决定使用3“×1”和4.5“×1”积木建造一个面板。为了结构完整性,积木之间的空间不得排成相邻的行。例如,下面的13.5“×3”面板是不可接受的,因为前两行中的块之间的一些空间对齐(如虚线所示)。

构建7.5“×1”面板的方法有2种,构建7.5“×2”面板的方法有2种,构建12“×3”面板的方法有4种,构建27“×5”面板的方式有7958种。 “小组。你的侄女有多少种不同的方式来建造一个48“×10”的面板?答案将适合64位整数。编写程序来计算答案。

这就是问题,我不知道从数学角度开始。我知道我需要为第一行计算所有可能的组合。但我不确定如何。然后,您可以在特定线程上计算下一行的所有可能组合,依此类推。然后每个第一行组合可以获得自己的线程并将其设置传递给递归算法,该算法将当前行与最后一行进行比较,并找到可能的答案。但我无法真正编程,因为我不知道如何计算任何行的可能组合。如果我这样做,那么也许我可以检查它是否是一个合法的行(没有两个块完全相互叠加(交错))并转到下一个。可能每行都是一个for循环,以代码的形式嵌套在下一行。但我再次不知道如何处理它的数学方面。

答案

我认为你初步掌握了这个问题。如果我理解你的想法,你应该在每个块放置上递归,而不是在每个行放置上 - 因为垂直定向的块将很快排除任何普通行。

这是我将要采用的方法:您将最终构建一个树(在内存中显式或隐式:树可以是在递归函数中传递的参数)。树的节点将是树的状态 - 因此根是“没有放置块”。你以某种方式放置了第一个块(我们将会这样做)并且代表一个新的状态。

目标是构建一组完整的叶子节点(填充板)和合法的(没有裂缝排列)。那我们怎么去那儿?

对于每个块放置,有4个“交替现实”:水平放置3x1块,垂直放置3x1(称为1x3),水平放置4.5x1,放置1x4.5。对于这些选项中的每一个,您将尝试“合法地”将块放置在行的下一个点。如果它是合法的(合法的是“块不与板边缘重叠,块不共享垂直边缘”),那么你可以接受该板作为中间状态并递归该新状态。如果不合法,那么必须放弃该州。

以这种方式思考,前4个子节点将是左下角的块[3x1,1x3,4.5x1,1x4.5]。这四种状态中的每一种都将在4种配置中的一种中具有“恰好在右侧”的块,依此类推。

为了在行中移动,当你到达右边缘时,我会找到“最低”的空白空间,当它们从左到右系上时,任意填充它们。当边缘粗糙时,这非常渴望修剪大型套装,但当水平平坦时仍然可以正常工作,就像你刚开始时一样。

实质上,对于每个中间状态,您的树将具有(最多)4个节点,边缘表示“尝试放置”。如果你不能合法地将块放在那个“尝试放置”的位置,你就不会从树中修复,修剪这种可能性和所有后代。

这种强力方法应该可以为您提供完整的电路板,即使其计算复杂性是天文数字。只有在你可以正确解决一些你应该考虑与线程并行化的问题时。递归问题往往很适合线程,因为每次递归通常可以并行化,而不会有太多的痛苦。只要确保你先做对了。

另一答案

这篇文章差不多5年了,但也许我的回答对某人有用。下面有两种解决方案。首先是没有多线程。第二个使用四个线程来解决问题。它计算48x4面板(48x10持续很长时间),但可以通过更改初始值来轻松修改它:

nbOfRows,nbOfCols,wallWidth和wall

没有多线程的解决方案:

import java.io.*;
import java.util.*;

class WallFlexOld
{
    static final float blocks[] = {3.0f, 4.5f};
    static final int nbOfRows = 4;
    static final int nbOfCols = 16;
    static final float wallWidth = 48.0f;
    static final float wall[][] = {
                                    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                                    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                                    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                                    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
                            };

    static long nbOfCombinations = 0;

    public static void main(String args[])
    {
        long startTime = System.currentTimeMillis();
        addBlock(0, 0);
        long workingTime = System.currentTimeMillis() - startTime;

        System.out.println("Working time: " + workingTime + "ms");
        System.out.println("noc: " + nbOfCombinations);
    }

    static void addBlock(int row, int col)
    {
        for(float b: blocks)
        {
            wall[row][col] = b;
            if(blockFit(row, col))
            {
                if(rowWidth(row) <= wallWidth)
                {
                    if(rowWidth(row) == wallWidth)
                    {
                        if(row == (nbOfRows - 1))
                            nbOfCombinations++;
                        else
                            addBlock(row + 1, 0);
                    }
                    else //rowWidth < wallWidth
                        addBlock(row, col + 1);

                }
            }   
            wall[row][col] = 0; 
        }
    }

    static float rowWidth(int row)
    {
        float width = 0;
        for(float b: wall[row])
            width = width + b;
        return width;
    }

    static boolean blockFit(int row, int col)
    {
        if(row == 0)
            return true;

        boolean fit = true;
        float currentLenght = 0;
        for(int i = 0; i < col; i++)
            currentLenght = currentLenght + wall[row][i];

        float lowerRowCurLenght = 0;
        for(float b: wall[row - 1])
        {
            lowerRowCurLenght = lowerRowCurLenght + b;
            if((currentLenght == lowerRowCurLenght) & (currentLenght != wallWidth))
                fit = false;
        }

        return fit;
    }
}

多线程解决方案:

import java.io.*;
import java.util.*;

class Wall implements Runnable
{
    private float blocks[];
    private int nbOfRows;
    private int nbOfCols;
    private float wallWidth;
    private float wall[][];
    private long nbOfCombinations = 0;
    private int row, col;

    public long getNbOfCombinations() { return this.nbOfCombinations; }

    Wall(float blocks[], int nbOfRows, int nbOfCols, float wallWidth, float wall[][], int row, int col)
    {
        this.blocks = blocks;
        this.nbOfRows = nbOfRows;
        this.nbOfCols = nbOfCols;
        this.wallWidth = wallWidth;
        this.wall = wall;
        this.row = row;
        this.col = col;
    }

    private boolean blockFit(int row, int col)
    {
        if(row == 0)
            return true;

        boolean fit = true;
        float currentLenght = 0;
        for(int i = 0; i < col; i++)
            currentLenght = currentLenght + wall[row][i];

        float lowerRowCurLenght = 0;
        for(float b: wall[row - 1])
        {
            lowerRowCurLenght = lowerRowCurLenght + b;
            if((currentLenght == lowerRowCurLenght) & (currentLenght != wallWidth))
                fit = false;
        }

        return fit;
    }

    private float rowWidth(int row)
    {
        float width = 0;
        for(float b: wall[row])
            width = width + b;
        return width;
    }

    private void addBlock(int row, int col)
    {
        for(float b: blocks)
        {
            wall[row][col] = b;
            if(blockFit(row, col))
            {
                if(rowWidth(row) <= wallWidth)
                {
                    if(rowWidth(row) == wallWidth)
                    {
                        if(row == (nbOfRows - 1))
                            nbOfCombinations++;
                        else
                            addBlock(row + 1, 0);
                    }
                    else //rowWidth < wallWidth
                    {
                        addBlock(row, col + 1);
                    }
                }
            }
            wall[row][col] = 0;
        }
    }


    @Override
    public void run()
    {
        addBlock(row, col);
    }
}

class WallMT
{
    static final float blocks[] = {3.0f, 4.5f};
    static final int nbOfRows = 4;
    static final int nbOfCols = 16;
    static final float wallWidth = 48.0f;
    static final float wall[][] = {
                                    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                                    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                                    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                                    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
                            };

    public static void main(String args[])
    {
        wall[0][0] = blocks[0];
        wall[0][1] = blocks[0];
        Wall myWall1 = new Wall(blocks, nbOfRows, nbOfCols, wallWidth, getWallCopy(wall), 0, 2);
        Thread t1 = new Thread(myWall1);

        wall[0][0] = blocks[0];
        wall[0][1] = blocks[1];
        Wall myWall2 = new Wall(blocks, nbOfRows, nbOfCols, wallWidth, getWallCopy(wall), 0, 2);
        Thread t2 = new Thread(myWall2);

        wall[0][0] = blocks[1];
        wall[0][1] = blocks[0];
        Wall myWall3 = new Wall(blocks, nbOfRows, nbOfCols, wallWidth, getWallCopy(wall), 0, 2);
        Thread t3 = new Thread(myWall3);

        wall[0][0] = blocks[1];
        wall[0][1] = blocks[1];
        Wall myWall4 = new Wall(blocks, nbOfRows, nbOfCols, wallWidth, getWallCopy(wall), 0, 2);
        Thread t4 = new Thread(myWall4);

        long startTime = System.currentTimeMillis();
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        try
        {
            t1.join();  
            t2.join();
            t3.join();  
            t4.join();  
        }
        catch(InterruptedException ie)
        {
            System.out.println("Thread " + t1 + " interrupted.");
        }

        long workingTime = System.currentTimeMillis() - startTime;

        System.out.println("Working time: " + workingTime + "ms");
        System.out.println("noc: " + (myWall1.getNbOfCombinations() + myWall2.getNbOfCombinations() + myWall3.getNbOfCombinations() + myWall4.getNbOfCombinations()));
    }

    static private float[][] getWallCopy(float wall[][])
    {
        float tmpWall[][] = new float[nbOfRows][nbOfCols];

        for(int i = 0; i < nbOfRows; i++)
            for(int j = 0; j < nbOfCols; j++)
                tmpWall[i][j] = wal

以上是关于非平凡Java数学练习的主要内容,如果未能解决你的问题,请参考以下文章

老罗笔记哪来的天才——练习中的平凡与伟大

如何让 GCC 用非平凡的 const/dest 实例化一个类实例?

数学之美番外篇:平凡而又神奇的贝叶斯方法

[转]数学之美番外篇:平凡而又神奇的贝叶斯方法

数学之美番外篇:平凡而又神奇的贝叶斯方法

树及其应用