当前位置: 首页 > 面试题库 >

编程竞赛问题:计数多胺

梁丘逸仙
2023-03-14
问题内容

请看我自己的答案,我想我做到了!

你好

编程竞赛的一个示例问题是编写一个程序,以找出在给定数量的宝石下可能有多少个多米诺骨牌。

因此,对于两块石头(n = 2),只有一个多米诺骨牌:

XX

您可能会认为这是第二种解决方案:

X
X

但事实并非如此。如果可以旋转多义字,它们并不是唯一的。

因此,对于4个石头(n = 4),有7个解决方案:

X
X   XX   X    X     X   X
X   X    XX   X    XX   XX   XX
X   X    X    XX   X     X   XX

该应用程序必须能够找到解决方案 1 <= n <=10

PS:不允许在Wikipedia上使用多氨基酸列表;)

编辑:当然,问题是:如何在Java,C / C ++,C#中做到这一点

我用Java启动了这个项目。但是后来我不得不承认我不知道如何使用有效的算法来构建多米诺骨牌。

这是我到目前为止的内容:

import java.util.ArrayList;
import java.util.List;


public class Main
{

    private int countPolyminos(int n)
    {
        hashes.clear();
        count = 0;
        boolean[][] matrix = new boolean[n][n];
        createPolyominos(matrix, n);
        return count;
    }

    private List<Integer> hashes = new ArrayList<Integer>();
    private int count;

    private void createPolyominos(boolean[][] matrix, int n)
    {
        if (n == 0)
        {
            boolean[][] cropped = cropMatrix(matrix); 
            int hash = hashMatrixOrientationIndependent(matrix);
            if (!hashes.contains(hash))
            {
                count++;
                hashes.add(hash);
            }
            return;
        }
    // Here is the real trouble!!
    // Then here something like; createPolyominos(matrix, n-1);
    // But, we need to keep in mind that the polyominos can have ramifications
    }

    public boolean[][] copy(boolean[][] matrix)
    {
        boolean[][] b = new boolean[matrix.length][matrix[0].length];
        for (int i = 0; i < matrix.length; ++i)
        {
            System.arraycopy(matrix[i], 0, b, 0, matrix[i].length);
        }
        return b;
    }

    public boolean[][] cropMatrix(boolean[][] matrix)
    {
        int l = 0, t = 0, r = 0, b = 0;
        // Left
        left: for (int x = 0; x < matrix.length; ++x)
        {
            for (int y = 0; y < matrix[x].length; ++y)
            {
                if (matrix[x][y])
                {
                    break left;
                }
            }
            l++;
        }
        // Right
        right: for (int x = matrix.length - 1; x >= 0; --x)
        {
            for (int y = 0; y < matrix[x].length; ++y)
            {
                if (matrix[x][y])
                {
                    break right;
                }
            }
            r++;
        }
        // Top
        top: for (int y = 0; y < matrix[0].length; ++y)
        {
            for (int x = 0; x < matrix.length; ++x)
            {
                if (matrix[x][y])
                {
                    break top;
                }
            }
            t++;
        }
        // Bottom
        bottom: for (int y = matrix[0].length; y >= 0; --y)
        {
            for (int x = 0; x < matrix.length; ++x)
            {
                if (matrix[x][y])
                {
                    break bottom;
                }
            }
            b++;
        }

        // Perform the real crop
        boolean[][] cropped = new boolean[matrix.length - l - r][matrix[0].length - t - b];
        for (int x = l; x < matrix.length - r; ++x)
        {
            System.arraycopy(matrix[x - l], t, cropped, 0, matrix[x].length - t - b);
        }
        return cropped;
    }

    public int hashMatrix(boolean[][] matrix)
    {
        int hash = 0;
        for (int x = 0; x < matrix.length; ++x)
        {
            for (int y = 0; y < matrix[x].length; ++y)
            {
                hash += matrix[x][y] ? (((x + 7) << 4) * ((y + 3) << 6) * 31) : ((((x+5) << 9) * (((y + x) + 18) << 7) * 53));
            }
        }
        return hash;
    }

    public int hashMatrixOrientationIndependent(boolean[][] matrix)
    {
        int hash = 0;
        hash += hashMatrix(matrix);
        for (int i = 0; i < 3; ++i)
        {
            matrix = rotateMatrixLeft(matrix);
            hash += hashMatrix(matrix);
        }
        return hash;
    }

    public boolean[][] rotateMatrixRight(boolean[][] matrix)
    {
        /* W and H are already swapped */
        int w = matrix.length;
        int h = matrix[0].length;
        boolean[][] ret = new boolean[h][w];
        for (int i = 0; i < h; ++i)
        {
            for (int j = 0; j < w; ++j)
            {
                ret[i][j] = matrix[w - j - 1][i];
            }
        }
        return ret;
    }

    public boolean[][] rotateMatrixLeft(boolean[][] matrix)
    {
        /* W and H are already swapped */
        int w = matrix.length;
        int h = matrix[0].length;
        boolean[][] ret = new boolean[h][w];
        for (int i = 0; i < h; ++i)
        {
            for (int j = 0; j < w; ++j)
            {
                ret[i][j] = matrix[j][h - i - 1];
            }
        }
        return ret;
    }

}

问题答案:

刚刚在Java中也解决了这个问题。由于所有这些似乎都存在性能问题。我也给你我的

董事会代表:

2个整数数组。1代表行,1代表列。

  • 旋转: column[i]=row[size-(i+1)]row[i] = reverse(column[i])其中是反向的位颠倒根据尺寸(大小= 4和开头的2位取:rev(1100) = 0011
  • 移位模块: row[i-1] = row[i]col[i]<<=1
  • 检查是否设置了位: (row[r] & (1<<c)) > 0
  • 板的唯一性: 当阵列行是唯一的时,板是唯一的。
  • 董事会哈希: 数组行的 哈希
  • ..

因此,这使所有操作变得快速。他们中的许多人本来应该是O(size²)2D数组表示形式,而不是现在O(size)

算法:

  • 从大小为1的块开始
  • 对于每种尺寸,从少1块石头的块开始。
  • 如果有可能添加石头。检查它是否已经添加到集合中。
  • 如果尚未添加。将其添加到此大小的解决方案中。
    • 将块添加到集合及其所有旋转中。(3轮,共4轮)
    • 重要的是,每次旋转后,将块尽可能向左/向左移动。
  • +特殊情况:接下来的2种情况执行相同的逻辑
    • 向右移动第一个块,并在第一列中添加石头
    • 将第一个块移至底部,并在第一行中添加石头

性能:

  • N=5 ,时间:3ms
  • N=10,时间:58ms
  • N=11,时间:166ms
  • N=12,时间:538ms
  • N=13,时间:2893ms
  • N=14,时间:17266ms
  • N=15,NA(堆空间不足)

代码:https :
//github.com/Samjayyy/logicpuzzles/tree/master/polyominos



 类似资料:
  • 我在一次公司入学考试中得到了以下问题。除4个测试用例外,所有测试用例均通过。有没有人能试着找出可能出现的情况,哪些可能会失败。问题和解决方案如下: 均值、中位数和模式 给定n个整数,求其平均中值和模式。您需要填写一个接受输入整数“input1”(1)的函数 平均数和中位数必须正确到小数点后六位。 平均值:定义为数组中所有数字的平均值。 中位数:定义为数组的中间元素。 如果n是偶数,则中值是两个中间

  • 问题内容: 最初,我的数据库中有两个表[Property]和[Employee]。 每个雇员可以有一个“家庭财产”,因此雇员表中有一个“财产”的HomePropertyID FK字段。 后来,我需要对这种情况进行建模,即尽管员工只有一个“房屋财产”,但确实在多个财产上工作或涵盖了多个财产。 因此,我创建了一个[Employee2Property]表,该表具有EmployeeID和PropertyI

  • 我正在尝试将一系列参数传递给不同的c线程。当NumThreads == 1时,程序运行良好,但是当NumThreads 创建线程的位置: 并且成员函数被调用: 来自前三个线程的控制台输出:{ 所以ID和样本索引被正确地传递给了线程,但是srcPoint怎么对所有三个线程都是相同的呢?!?

  • 我有以下资料: streamB中的消息需要使用表A中的数据进行丰富。 示例数据: 在一个完美的世界里,我想做什么 不幸的是,这对我不起作用,因为我的数据是这样的:每次将消息写入主题a时,相应的消息也会写入主题B(源是单个DB事务)。现在,在这个初始“创建”事务之后,主题B将继续接收更多消息。有时,主题B上会出现每秒数个事件,但对于给定的键,也可能出现连续事件间隔数小时的情况。 简单的解决方案不起作

  • 本书主要面向 CTF Pwn 初学者,专注于 Linux 二进制安全。全书包含12章,从二进制底层讲起,结合源码详细分析了常见二进制安全漏洞、缓解机制以及漏洞利用方法,并辅以分析工具和环境搭建的讲解,循序渐进,让读者可以进行系统性的学习。

  • 问题内容: (注意:这是针对MS SQL Server的) 假设您有一个具有主键标识列和CODE列的表ABC。我们希望此处的每一行都有一个唯一的,顺序生成的代码(基于一些典型的校验位公式)。 假设您有另一个仅具有一行的表DEF,该表存储下一个可用的CODE(想象一个简单的自动编号)。 我知道像下面这样的逻辑将呈现一种竞争状态,其中两个用户可能最终得到相同的CODE: 我知道,两个用户可能会卡在步骤