【发布时间】:2011-06-06 18:01:34
【问题描述】:
请看我自己的回答,我想我做到了!
嗨,
编程竞赛的一个示例问题是编写一个程序,找出给定数量的石头可能有多少多骨牌。
所以对于两块石头 (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:不允许使用list of polyominos on 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;
}
}
【问题讨论】:
-
你应该解释一下什么是多骨牌
-
您当前的代码以何种方式失败?
-
@Falmarri 他确实链接到 Wikipedia 上 polyominos 的 lsit,并且“polyomino”一词的搜索结果基本上可以保证为您提供所需的信息
-
在 [wiki 文章] (en.wikipedia.org/wiki/Polyomino#Enumeration_of_polyominoes) 中,您正在计算 单面多骨牌 的数量