答案 0 :(得分:0)
正如Yves Daoust所说,解决这个问题的算法会很慢。第一个挑战是确定哪些方块可以组合成适合你的大方块。然后弄清楚它们是否适合那里。
我会先按区域过滤。
要回答第一部分,您需要寻找适合您的大方块的方块组合。可能有多种组合,因为5x5平方占据相同面积,3x3占4x4平方。这本身就是一个O(2 ^ n)问题。
然后尝试安排他们。
我会制作一个大广场大小的矩阵。然后从最顶部开始,然后最右边的索引通过将矩阵位置标记为该正方形占据而添加到正方形中。然后根据先前的规则添加未使用的方块,移动到下一个未占用的空间。如果没有方形拟合,则删除前一个方格并继续下一个方格。这是一种请求递归的方法。
正如我在开头所说的那样,这是一种缓慢的方式,但如果存在,它将为您提供解决方案。
答案 1 :(得分:0)
我使用动态编程方法来解决这个问题。但它一直工作到n~50。我将解决方案存储为效率的位集:
您可以自己编译代码: $ g ++ -O3 -std = c ++ 11 squares.cpp -o squares
#include <bitset>
#include <iostream>
#include <list>
#include <vector>
using namespace std;
constexpr auto N = 116;
class FastSquareList {
public:
FastSquareList() = default;
FastSquareList(int i) { mask_.set(i); }
FastSquareList operator+(int i) const {
FastSquareList result = *this;
result.mask_.set(i);
return result;
}
bool has(int i) const { return mask_.test(i); }
void display() const {
for (auto i = 1; i <= N; ++i) {
if (has(i)) {
cout << i * i << " ";
}
}
cout << endl;
}
private:
bitset<N + 1> mask_;
};
int main() {
int n;
cin >> n;
vector<list<FastSquareList> > v(n * n + 1);
for (int i = 1; i <= n; ++i) {
v[i * i].push_back(i);
for (int a = i * i + 1; a <= n * n; ++a) {
int p = a - i * i;
for (const auto& l : v[p]) {
if (l.has(i)) {
continue;
}
v[a].emplace_back(l + i);
}
}
}
for (const auto& l : v[n * n]) {
l.display();
}
cout << "solutions count = " << v[n*n].size() << endl;
return 0;
}
一个例子:
$ ./Squares
15
9 16 36 64 100
25 36 64 100
1 4 9 16 25 49 121
4 36 64 121
4 100 121
4 16 25 36 144
1 16 64 144
81 144
4 16 36 169
4 9 16 196
4 25 196
225
solutions count = 12