Hãy tưởng tượng một thế giới dựa trên khối lập phương (như Minecraft, Trove hoặc Cube World) nơi mọi thứ được tạo thành từ các hình khối có kích thước giống hệt nhau và tất cả các hình khối đều cùng loại .
Mục tiêu là đại diện cho thế giới với số lượng hộp hình chữ nhật ít nhất (bằng cách hợp nhất các hình khối nhưng vẫn giữ hình dạng lồi (hay còn gọi là hình hộp hình chữ nhật)). Thuật toán của tôi thành công ở đây, nhưng hiệu suất của nó quá chậm so với mục đích của nó. Có thuật toán nhanh hơn?
Mã giả mã C # cho thuật toán của tôi về cơ bản là:
struct Coordinate { int x,y,z; }; //<-- integer based grid
HashSet<Coordinate> world; // <-- contains all the cubes
//width, height, and length represent how many cubes it spans
struct RectangularBox { Coordinate coord; int width,height,length; }
void Begin()
{
List<RectangularBox> fewestBoxes = new List<RectangularBox>();
while(world.Count > 0)
{
RectangularBox currentLargest = ExtractLargest();
fewestBoxes.Add(currentLargest);
world.RemoveRange(currentLargest.ContainedCubes());
}
//done; `fewestBoxes` contains the fewest rectangular boxes needed.
}
private RectangularBox ExtractLargest()
{
RectangularBox largestBox = new RectangularBox();
foreach (Coordinate origin in world)
{
RectangularBox box = FindMaximumSpan(origin);
if (box.CalculateVolume() >= largestBox.CalculateVolume())
largestBox = box;
}
return largestBox;
}
private RectangularBox FindMaximumSpan(Coordinate origin)
{
int maxX, maxY,maxZ;
while (world.Contains(origin.Offset(maxX, 0, 0))) maxX++;
while (world.Contains(origin.Offset(0, maxY, 0))) maxY++;
while (world.Contains(origin.Offset(0, 0, maxZ))) maxZ++;
RectangularBox largestBox;
for (int extentX = 0; extentX <= maxX; extentX++)
for (int extentY = 0; extentY <= maxY; extentY++)
for (int extentZ = 0; extentZ <= maxZ; extentZ++)
{
int lengthX = extentX + 1;
int lengthY = extentY + 1;
int lengthZ = extentZ + 1;
if (BoxIsFilledWithCubes(origin, lengthX, lengthY, lengthZ))
{
int totalVolume = lengthX * lengthY * lengthZ;
if (totalVolume >= largestBox.ComputeVolume())
largestBox = new RectangularBox(origin, lengthX, lengthY, lengthZ);
}
else
break;
}
return largestBox;
}
private bool BoxIsFilledWithCubes(Coordinate coord,
int lengthX, int lengthY, int lengthZ)
{
for (int gX = 0; gX < lengthX; gX++)
for (int gY = 0; gY < lengthY; gY++)
for (int gZ = 0; gZ < lengthZ; gZ++)
if (!world.Contains(coord.Offset(gX, gY, gZ)))
return false;
return true;
}
Về cơ bản, đối với mọi khối trên thế giới, trước tiên, người ta sẽ tìm thấy có bao nhiêu khối liên kết trong mỗi ba chiều dương (+ X, + Y, + Z). Và sau đó, nó sẽ lấp đầy khối lượng đó và kiểm tra khối lượng lớn nhất không thiếu bất kỳ khối nào.
Cập nhật: Vì dường như tôi đã ngụ ý rằng đây là công cụ kết xuất của trò chơi, tôi chỉ muốn làm rõ, đây không phải là công cụ kết xuất của trò chơi; nó dành cho trình chuyển đổi tập tin; không có GUI.