非平凡Java数学练习

时间:2013-02-01 04:06:21

标签: java multithreading math recursion geometry

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

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

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

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

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

2 个答案:

答案 0 :(得分:1)

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

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

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

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

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

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

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

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

答案 1 :(得分:1)

这篇文章已有近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] = wall[i][j];

        return tmpWall;
    }
}